<android> 第三方支付sdk接入 支付宝、微信支付

来源:互联网 发布:哈尔滨数据开放 编辑:程序博客网 时间:2024/04/29 22:46
第三方sdk接入  支付宝  微信支付


对于一些接入第三方的东西,感觉实在是没多少可说的,干脆我就整理成了一个帖子,一块简要说说吧。

一.android接入支付——支付宝

支付宝接入的流程啥的我就不多说了,网上资料一大堆,直接说和后台、和平台的交互以及代码的书写吧。首先是在蚂蚁金服开放平台申请企业账号、签约(客户,或项目经理做),然后是创建应用:

签约会自动生成一个应用2.0签约应用,以及appid,当然我们自己也需要创建一个应用,并且提交资料,包括生成的公钥,应用包名等等。


设置好之后就ok了,然后down下那段支付宝经典的代码:

/** * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成; * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成; * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; * orderInfo的获取必须来自服务端; */Log.e("===", "订单信息:" + order_info);order_info = order_info.substring(1);order_info = order_info.replaceAll("&amp;", "&");Log.e("===", "处理后订单信息:" + order_info);
========= 根据支付宝的提示 加签过程放到服务器小哥那 所以这段代码可忽略哦 ===========boolean rsa2 = (RSA2_PRIVATE.length() > 0);Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);String orderParam = OrderInfoUtil2_0.buildOrderParam(params);String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);final String orderInfo = orderParam + "&" + sign;
==================================================
Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask(PayActivity.this); Map<String, String> result = alipay.payV2(order_info, true); android.util.Log.i("msp", result.toString()); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); }};Thread payThread = new Thread(payRunnable);payThread.start();
  这个时候有经验的大咖就会问了,你为啥在order_info放到payV2方法之前还对order_info截串,截完还替换&,这个我一开始也不想做,
但是从php那边拿过来order_info后我调起支付,总是会出现Ali40247的错误,不用看着指定是参数不对啊,仔细观察了下返回过来的order_info
发现这个串前边有一个自带的“ ~ ”,不知道是服务器那边的事还是我这边框架的问题,然后我干脆就直接1索引截取了,并且还发现,json数据
过来后它竟然把&转义了,把“&”转换成了“&amp”,所以再全部替换喽。
  有一次支付宝支付还遇到一个奇葩问题,也是报Ali40247,但是就是找不到原因,后来我发现是我设置公钥设置在RSA一栏了,而我们后台调用的则使
RSA2,所以就出错了,直接让后台改成RSA就ok了。有时候就是因为这么一点小小的问题就会导致到问题。
 还有一次报了Ali59错误码,这个代表你的支付金额为空啦,最低0.01就好了。
  接着就是接受结果的地方,不多做解释,9000是成功,如果出错就打印String re = msg.obj.toString();,查看错误信息。还有就是关于appID,大家
也看到了,只有在本地签名的时候有用到,而支付宝不推荐本地做签名,所以我们直接从后台那边拿到就可以。那几个字段全都是后台走的api,返回
过来的数据好了,支付宝就啰嗦这么多。
二.android接入支付——微信
  微信首先先说一下这个平台的问题,都知道微信有好多个平台,1.微信公众平台,2.微信开放平台,3.微信商户平台,还有没有4我也不知道了就,那么我们用的是开放平台,我们再申请开放平台的时候会生成一个商户平台账号,那么我们用商户平台是干啥的呢,其实它是统计、汇总一些支付信息,是属于商家需要的一账号,不要被它所干扰,而公众平台则是公众号里面做支付等功能用的平台,也与我们原生app无关。
  啰嗦那么多,接下来就开始进入正题,同支付宝一样,先创建账号,创建应用(包名,签名)后进行商家认证,申请支付能力:
  搞完之后就会拿到AppID和AppSecret,配置代码:
api = WXAPIFactory.createWXAPI(PayActivity.this, "wxxxxxxxxxxxxxxx");api.registerApp("wxxxxxxxxxxxxxxx");
然后上关键代码:

String str = "Sign=WXPay";if (RequestCode == 100) {    Log.e("=========", "微信支付内容:" + content);    Gson gson = new Gson();    WxpayBean wxpayBean = gson.fromJson(content, WxpayBean.class);    if (Integer.parseInt(wxpayBean.getCode()) == 200) {        WxpayBean.DataBean data = wxpayBean.getData();        SortedMap<String, Object> params = new TreeMap<String, Object>();        params.put("appid", data.getAPPID());        params.put("partnerid", data.getMCH_ID());        params.put("prepayid", data.getPREPAY_ID());        params.put("package", "Sign=WXPay");        params.put("noncestr", data.getNONCE_STR());        params.put("timestamp", data.getTimestamp() + "");        String sign = createSign(params);        PayReq req = new PayReq();        req.appId = data.getAPPID();  //后台和本地都可        req.partnerId = data.getMCH_ID(); //后台给出  微信支付分配的商户号        req.prepayId = data.getPREPAY_ID();  //后台给出  预支付订单号,app服务器调用“统一下单”接口获取        req.nonceStr = data.getNONCE_STR(); //后台给出 /随机字符串,不长于32位        req.timeStamp = data.getTimestamp() + ""; //时间戳        req.packageValue = str;   //固定值Sign=WXPay        req.sign = sign;  //签名        Toast.makeText(PayActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();        // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信        api.sendReq(req);    }}
  都说微信支付坑,坑在哪里,坑在出现错误后结果返回-1,而有时候就不会给提示,后来经过我和后台的反复测试,在一篇帖子的引导下,确定了是签名的问题,
后台做了签名,而我直接拿取的后台的sign填入其中才导致了这样的问题,那篇博客的大意好像是说因为时间戳的原因,拉不起来支付,因为签名的时候需要混入时间戳的,所以我
们商量一下我本地也做了签名,但目的不是为了签名而签名,而是为了拉起来本地支付接口,实际上支付走的签名信息还是后台做的,有时间会找到那篇文章链接放
在这,方法:
    public static String createSign(SortedMap<String, Object> parameters) {        StringBuffer sb = new StringBuffer();        Set es = parameters.entrySet();        Iterator it = es.iterator();        while (it.hasNext()) {            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=" + "xxxxxxxxxxxxxxxx");//        String sign = MD5Utils.encode(sb.toString()).toUpperCase();        String sign = getPwd(sb.toString()).toUpperCase();        return sign;    }    /**     * @author CQY13 MD5加密工具类     */    public static String getPwd(String pwd) {        try {            // 创建加密对象            MessageDigest digest = MessageDigest.getInstance("md5");            // 调用加密对象的方法,加密的动作已经完成            byte[] bs = digest.digest(pwd.getBytes());            // 接下来,我们要对加密后的结果,进行优化,按照mysql的优化思路走            // mysql的优化思路:            // 第一步,将数据全部转换成正数:            String hexString = "";            for (byte b : bs) {                // 第一步,将数据全部转换成正数:                // 解释:为什么采用b&255                /*                 * b:它本来是一个byte类型的数据(1个字节) 255:是一个int类型的数据(4个字节)                 * byte类型的数据与int类型的数据进行运算,会自动类型提升为int类型 eg: b: 1001 1100(原始数据)                 * 运算时: b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000                 * 0000 0000 0000 0000 0000 1111 1111 结果:0000 0000 0000 0000                 * 0000 0000 1001 1100 此时的temp是一个int类型的整数                 */                int temp = b & 255;                // 第二步,将所有的数据转换成16进制的形式                // 注意:转换的时候注意if正数>=0&&<16,那么如果使用Integer.toHexString(),可能会造成缺少位数                // 因此,需要对temp进行判断                if (temp < 16 && temp >= 0) {                    // 手动补上一个“0”                    hexString = hexString + "0" + Integer.toHexString(temp);                } else {                    hexString = hexString + Integer.toHexString(temp);                }            }            return hexString;        } catch (NoSuchAlgorithmException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return "";  
经过签名后果断就拉起支付过来,也不会返回-1了。 这个情况也不知道是后台还是我的原因,感觉这样解决还是太low,等我研究透了,再帖上原因,也希望大家有知道原因的,
楼下留言。互相学习。
然后就是回调了,WXPayEntryActivity 接受结果,通过eventbus或handler传递到其他页面结果(此类及所在包均不可改名)。




阅读全文
0 0
原创粉丝点击