Android 微信支付和支付宝支付 快速接入

现在的支付潮流莫过于微信跟支付宝了,最近我们项目涉及到会员需求,就用到微信支付跟支付宝支付,说实话接入之前会觉得这个复杂,等真正去动手实践的时候才觉得狠简单,真的狠简单。从接入到支付一步到位,Run完直接调起了微信跟支付宝。接入前也看了这两个支付的详细接入文档,但是看是一码事,做也是一码事。所以实践很重要。

  • 之所以说狠简单而且快速接入,主要是因为我们公司的运维后台很给力,把微信的一些请求参数,全部后台返回给我们,我们直接用实体是接受拿到就好。
先说下微信支付吧,毕竟相对于支付而言,还是支付宝简单快速一点,就留到后面说了

1.如果你已经成功集成了微信登录和分享,直接用你的 libammsdk.jar和 WECHAT_APP_ID就可以了, 那么下面帮你快速集成微信支付。

2.接入前可以看看上面链接的文档,不过微信官方的文档写的不够好,好多开发者吐槽,至今也没改善点啥。
3.好了直接说接入,接入微信支付SDK前准备下面三个东西,如果你集成了微信分享,登录那只需要一个 WXPayEntryActivity 类就行了
① 微信支付的APPID
② 微信支付依赖包 -------- libammsdk.jar
③ 一个Activity类 ----------- WXPayEntryActivity

  • 这里需要特别说明一下,这个WXPayEntryActivity 类,直接从微信官方下载的Demo代码中copy到自己的工程中即可,这个页面是在你调起微信支付完成支付(或取消或失败)后,再回到你的App时会调用的一个页面。页面的布局可以是你自定义的布局(一般做法是直接注释掉这个布局)
    网上copy的一张图讲解:
WXPayEntryActivity 的路径

4、WXPayEntryActivity中的布局是可以自定义的,如果你不需要展示什么布局,而是要跳转页面,把这段代码删除即可

/**
 * -Created by Luke on 2017/2/14.
 */
public class WXPayEntryActivity extends AppCompatActivity  {
    private static final String TAG = WXPayEntryActivity.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.pay_result);
        BaseApplication.api.handleIntent(getIntent(), this);
    }
}
WECHAT_APP_ID 已经在BaseApplication中定义了 在这里不需要再写

5.下面是回调的逻辑,官方是这样的图


官方回调页面
  • 我这边就简单的演示下支付成功的地方
    @Override
    public void onResp(BaseResp resp) {

        LogUtil.d(TAG, "Luke = " + resp.toString());
        
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            int code = resp.errCode;
            switch (code) {
                case 0:
                    ToastUtil.show("支付成功");
                    break;
                case -1:
                    ToastUtil.show("支付失败");
                    finish();
                    break;
                case -2:
                    ToastUtil.show("支付取消");
                    finish();
                    break;
                default:
                    ToastUtil.show("支付失败");
                    setResult(RESULT_OK);
                    finish();
                    break;
            }
        }
    }

接下来咱就把这个WXPayEntryActivity放在清单manifest文件里面注册,然后加上exported属性,设置为true:

<activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/Theme.AppCompat.NoActionBar"/>
注意的地方:
  • 0 成功 展示成功页面
  • -1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
  • -2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。

6.这个类中的其余的回调方法,我们都不需要去操作。然后我们就可以开始支付了,蛮简单

  • 下面是请求的参数列表,我们都是服务器端返回,包括APPID,直接用已经正式的sign。
微信支付请求参数列表
  • 大概的支付流程是
    ① 点击支付的时候创建订单,获取订单号orderNumber (或者在需要获取订单号的时候获取)
    ② 通过你的价格和这个orderNumber去请求微信返回的一堆参数,以及调起支付页面:
    下面是关键的一步:

//PrePayWeChatEntity 服务器返回给我们微信支付的参数

private void WeChatPay(PrePayWeChatEntity data) {

        if (null == data) {
             //判断是否为空。丢一个toast,给个提示。比如服务器异常,错误啥的
            return;
        }

        IWXAPI api = WXAPIFactory.createWXAPI(this, data.getAppid());
        
        if (!isWXAppInstalledAndSupported(api)) {
            // throw new WeChartNoFoundException();
            ToastUtil.show(getString(R.string.text_uninstalled_wchat));
            
            return;
        }

        //data  根据服务器返回的json数据创建的实体类对象
        PayReq req = new PayReq();

        req.appId = data.getAppid();
        
        req.partnerId = data.getPartnerid();
        
        req.prepayId = data.getPrepayid();
        
        req.packageValue = data.getPkgstr();
        
        req.nonceStr = data.getNoncestr();
        
        req.timeStamp = data.getTimestamp();
        
        req.sign = data.getSign();

        api.registerApp(data.getAppid());
        
        //发起请求
        api.sendReq(req);
    }

7.到这就是成功了,调起了微信支付。再回到 WXPayEntryActivity 中去判断成功后的动作,例如支付完成跳转一个成功的页面finish();也许是用户取消,和异常的支付失败,可以在这个逻辑中去请求订单的状态是怎么样的。
8.最后一个问题就是关于微信开放平台签名的问题。只要你手机上的程序的签名和你在微信平台登记的签名一致即可,无论是debug版本,还是release版本,都是可以的,默认都可以用release的签名

到这微信支付就愉快的结束了

支付宝支付,这个比微信稍微简单那么点,同样在请求参数服务端返回的情况下
  • 支付宝开放平台 在这个平台申请我们的支付功能:
  • 注意一点就是个人不能申请的,只能是企业,so 我demo里面的用的一些资料也是demo里面的

1.进入支付宝开放平台,注册账户并登录。


官网地址

支付宝移动支付

2.登录成功后,点击管理中心创建应用(创建应用时,注意命名规范)。

  • 下载 alipaySdk-20161222.jar 和 alipay_demo

  • 将demo里面的alipaySdk-20161222.jar拷贝到我们工程的libs下,并添加到依赖中

  • 跟微信一样在清单文件中注册下这两个Activity

  <activity
    android:name="com.alipay.sdk.app.H5PayActivity"
    android:configChanges="orientation|keyboardHidden|navigation"
    android:exported="false"
    android:screenOrientation="behind">
</activity>
<activity
    android:name="com.alipay.sdk.auth.AuthActivity"
    android:configChanges="orientation|keyboardHidden|navigation"
    android:exported="false"
    android:screenOrientation="behind">
</activity>

3.设置应用公钥

4.生成密钥

5.点击上方的支付宝密钥生成器下载下jar包之后解压

6.点击密钥生成器之后回弹出黑窗口,等几秒之后弹出生成器窗口

7.跟微信的流程相差无几。拿到价格和订单号,就可以去请求支付的地址了,然后用这些参数回调支付

    //orderNum,  orderInfo,  sign,  signType  服务器端返回,本地生成也是OK的
    private void requestAlipay(String orderNum, String orderInfo, String sign, String signType) {

        try {

            // 对sign做URL编码
            sign = URLEncoder.encode(sign, "UTF-8");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //  整的符合支付宝参数规范的订单信息
        final String payInfo = orderInfo + "&sign=\"" + sign + "\"&sign_type=\"" + signType + "\"";

        //lambda    此处  () ->  为lambda 表达式写法
        Runnable payRunnable = () -> {
            // 构造PayTask 对象
            PayTask payTask = new PayTask(this);
            // 调用支付接口,获取支付结果
            String result = payTask.pay(payInfo, true);

            if (null == result) {
                result = "out_trade_no={" + orderNum + "}";
            } else {
                result += ";out_trade_no={" + orderNum + "}";
            }

            Message msg = new Message();
            msg.what = SDK_PAY_FLAG;
            msg.obj = result;
            mHandler.sendMessage(msg);
        };

        // 必须异步调用
        Thread payThread = new Thread(payRunnable);
        payThread.start();
    }

上述生成的这些东西一般都是后台返回的,当然我们本地生成也是可以的,所以我就大概的说下流程

  • 处理支付结果:
 @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {

        @SuppressWarnings("unused")
        public void handleMessage(Message msg) {
            switch (msg.what) {

                case SDK_PAY_FLAG: {
                    @SuppressWarnings("unchecked")
                    PayResult payResult = new PayResult((Map<String, String>) msg.obj);
                    /**
                     对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
                     */
                    String resultInfo = payResult.getResult();// 同步返回需要验证的信息
                    String resultStatus = payResult.getResultStatus();
                    // 判断resultStatus 为9000则代表支付成功
                    if (TextUtils.equals(resultStatus, "9000")) {
                        // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                        Toast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    } else {
                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                        Toast.makeText(PayDemoActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
                    }
                    break;
                }

                case SDK_AUTH_FLAG: {
                    @SuppressWarnings("unchecked")
                    AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
                    String resultStatus = authResult.getResultStatus();

                    // 判断resultStatus 为“9000”且result_code
                    // 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档
                    if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                        // 获取alipay_open_id,调支付时作为参数extern_token 的value
                        // 传入,则支付账户为该授权账户
                        Toast.makeText(PayDemoActivity.this,
                                "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        // 其他状态值则为授权失败
                        Toast.makeText(PayDemoActivity.this,
                                "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                    }
                    break;
                }

                default:
                    break;
            }
        }

        ;
    };

  • 到这儿就支付成功了,提示用户的逻辑,我们得从服务器确认是否正在支付了,查询是否支付成功的状态。根据服务器端返回的判断码来处理支付之后的一些动作。

  • 接入的时候有啥问题可以随时跟我谈论,我想这些会给你们一些帮助,记录就是在脑子里过一遍,也许是最好的成长。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容