(Android集成支付宝支付)react-native实现支付宝支付
网上关于RN的支付宝支付组件大部分都是IOS的,Android要实现支付宝支付只剩下走原生这一步了。
整体思路:
1、在蚂蚁金服开放平台申请应用
2、在android原生集成支付宝
3、封装android原生
4、RN与android的通信
一、准备工作
1、在蚂蚁金服开放平台https://docs.open.alipay.com/204/105051/ 按照官方提示创建应用,添加app支付的功能。
2、在审核通过后可以拿到调用支付所需要的参数。
3、下载官方的Demo和SDKhttps://docs.open.alipay.com/54/104509
解压项目,用Android Studio打开alipay_demo项目,核心代码都在这个文件夹中。
二、项目操作
1、初始化zfbDemo的RN项目。并用Android Studio打开android部分。
2、在zfbDemo/android/app/目录下新建libs文件夹,将官网下载的alipay_demo中的libs下的sdk复制到新建的libs文件夹下。并右键 Add as Library添加到项目中。
3、在AndroidManifest.xml文件中加入注册声明:
和权限声明:
4、我们直接实现点击RN中的按钮调出支付宝支付页面。
创建一个类继承ReactContextBaseJavaModule,这个类放入被RN调用的方法封装成有个原生模块
新建一个MyNativeModule的类,内容:
package com.zfbdemo;import android.content.Context;import android.content.Intent;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;/** * Created by admin on 2017/11/3. */public class MyNativeModule extends ReactContextBaseJavaModule { private Context mContext; //构造方法 public MyNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } @Override public String getName() { //MyNativeModule 需要此名字来调用该类方法 return "MyNativeModule"; } //函数不能有返回值,被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数发送消息给RN //rnCallNative为RN需要调用的方法 @ReactMethod public void rnCallNative(){ }}
创建一个类实现接口ReactPackage包管理器,把上面一步创建的类添加到原生模块(nativeModule)列表里
新建一个MyReactPackge的类,内容:
package com.zfbdemo;import com.facebook.react.ReactPackage;import com.facebook.react.bridge.JavaScriptModule;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Collections;import java.util.List;/** * Created by admin on 2017/11/3. */public class MyReactPackge implements ReactPackage { @Override public List createNativeModules(ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new MyNativeModule(reactContext)); return modules; } @Override public List> createJSModules() { return Collections.emptyList(); } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); }}
在MainApplication中加入new MyReactPackge()
@Override protected List getPackages() { return Arrays.asList( new MainReactPackage(), new MyReactPackge()//添加这一句 ); }
到现在,RN调用的原生Android方法就封装好了,下一步就需要在方法里面调用支付了,不再一一叙述,直接贴代码:
tip:这一块只是为了实现支付功能的演示,真正的项目是需要后台加密返回orderInfo的。
先引入一些文件:
将官方demo中的这些文件复制过来,然后逐个打开,有包名之类的错误的改正。
将MyNativeModule.Java文件改为以下内容:
package com.zfbdemo;import android.annotation.SuppressLint;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.widget.Toast;import com.alipay.sdk.app.PayTask;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;import com.zfbdemo.util.OrderInfoUtil2_0;import java.util.Map;/** * Created by admin on 2017/11/3. */public class MyNativeModule extends ReactContextBaseJavaModule { /** 支付宝支付业务:入参app_id */ public static final String APPID = "申请的appid"; /** 支付宝账户登录授权业务:入参pid值 */ public static final String PID = "申请的pid"; /** 支付宝账户登录授权业务:入参target_id值 */ public static final String TARGET_ID = ""; /** 商户私钥,pkcs8格式 */ /** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */ /** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */ /** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */ /** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */ /** 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1 */ public static final String RSA2_PRIVATE = "申请应用中的私钥"; public static final String RSA_PRIVATE = ""; private static final int SDK_PAY_FLAG = 1; private static final int SDK_AUTH_FLAG = 2; private Context mContext; //构造方法 public MyNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } @Override public String getName() { //MyNativeModule 需要此名字来调用该类方法 return "MyNativeModule"; } //函数不能有返回值,被调用的原生代码是异步的,原生代码执行结束之后只能通过回调函数发送消息给RN //rnCallNative为RN需要调用的方法 @ReactMethod public void rnCallNative(){ payV2(); } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler(Looper.getMainLooper()) { @SuppressWarnings("unused") public void handleMessage(Message msg) { switch (msg.what) { case SDK_PAY_FLAG: { @SuppressWarnings("unchecked") PayResult payResult = new PayResult((Map) msg.obj); /** 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 */ String resultInfo = payResult.getResult();// 同步返回需要验证的信息 String resultStatus = payResult.getResultStatus(); // 判断resultStatus 为9000则代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。 Toast.makeText(mContext, "支付成功", Toast.LENGTH_SHORT).show(); } else { // 该笔订单真实的支付结果,需要依赖服务端的异步通知。 Toast.makeText(mContext, "支付失败", Toast.LENGTH_SHORT).show(); } break; } case SDK_AUTH_FLAG: { @SuppressWarnings("unchecked") AuthResult authResult = new AuthResult((Map) 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(mContext, "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT) .show(); } else { // 其他状态值则为授权失败 Toast.makeText(mContext, "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show(); } break; } default: break; } }; }; public void payV2() { /** * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成; * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成; * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; * * orderInfo的获取必须来自服务端; */ boolean rsa2 = (RSA2_PRIVATE.length() > 0); Map 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(getCurrentActivity()); Map result = alipay.payV2(orderInfo, true); 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(); }}
在JS中:
import { AppRegistry, StyleSheet, Text, View, NativeModules, TouchableOpacity} from 'react-native';
{ NativeModules.MyNativeModule.rnCallNative() }}> 调用支付
此时点击RN中的按钮会直接调出支付宝支付。
再次提醒orderInfo必须从后台获得(防止信息泄密)
当手机安装了支付宝会调用支付宝支付,如果没有支付宝会登录网页版的支付宝。
需要注意一点,当应用设置了状态栏沉浸模式,网页版的支付宝的activity会被提上来影响美观,需要在AndroidManifest.xml中加一句:
android:theme="@android:style/Theme"
更多相关文章
- Android 中自定义控件和属性(attr.xml,declare-styleable,TypedA
- 移动应用开发:如何创建自定义Android代码模板
- Android 用代码动态添加View(ViewGroup.addView()),并进行动态添加
- [Android]LayoutInflater的inflate方法半详解
- Android应用程序进程启动过程的源代码分析(1)
- Android与Unity交互调用mUnityPlayer.quit()方法退出返回上一个A
- Android API之Typeface代码演示