登录按钮

ReactNative接入支付宝支付

写在前面

重申一下,ReactNative开发的AppNativeApp,不是WebApp或者HybridApp,所以我们需要开通的是支付宝的App支付功能,别申请错了。申请完成之后就可以接下去开发了。

支付宝支付

接入支付宝支付前建议先查看 支付宝官方文档,先按照要求创建应用并完成配置。不过要注意以下两点:

第一,App支付不能在沙箱做测试,所以我们需要先 “上线” 应用,这个过程会有1天的审核时间。 
第二,调试时建议添加个一分钱的商品作为测试商品,开发免不了要支付几次。

安装模块

支付宝支付我们使用了ReactNative社区推荐的 react-native-yunpeng-alipay 模块,可以使用 npm 安装

npm install react-native-yunpeng-alipay --save 

link引用

最新版 React Native (>=0.31) 已经支持 link 命令,不需要再使用三方的 rnpm来 link 引用了。

react-native link react-native-yunpeng-alipay

这个操作会把 react-native-yunpeng-alipay 模块下的客户端模块自动映射到 ReactNative工程的对应的 IOS和 Android目录里。 注意,自动link并不是万能的,有些模块我们需要再手动添加一些引用。

IOS端配置

对于IOS端,除了上面的link操作之外,我们还需要手动做下面的三件事:

添加Frameworks和Libraries

打开xcode,TARGET -> General -> Linked Frameworks and Libraries ,添加

  • CoreMotion.framework
  • CoreTelephony.framework
  • libc++
  • libz

xcode截图

添加 URL Schema

打开 Info.plist,添加一项URL types

URL types

触发回调

打开 AppDelegate.m,添加一个函数来触发支付完成后的回调

#import "AlipayModule.h"
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  [AlipayModule handleCallback:url];
  return YES;
}

Android端配置

Android端配置比较简单,除了上面的link操作外,我们还需要修改Manifest文件

修改Manifest

在商户应用工程的AndroidManifest.xml文件里面添加声明:

<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>

和权限声明:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

添加混淆规则

在商户应用工程的proguard-project.txt里添加以下相关规则:

-libraryjars libs/alipaySDK-20150602.jar

-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}

Action封装

我们的App开发采用的是redux框架,为了方便使用,我把支付宝支付封装成了Action,你可以参考一下。

/**
 * @desc 三方支付
 * @author Jafeney
 * @detetime 2016-11-08
 **/

import Alipay from 'react-native-yunpeng-alipay'
import * as CONFIG from '../config'

export function alipay(opt) {
  return (dispatch) => {
    const uri = `http://${ CONFIG.API_URI }/alipay/pay`;  /*支付接口*/
    const headers = {
      ...CONFIG.HEADERS,
      Authorization: opt.token
    };
    /*调用支付接口*/
    fetch(uri, {method: 'POST', headers: headers, body: JSON.stringify(opt.body)})
      .then((response) => {
        if (response.status === 200) {
          return response.json()
        } else {
          return {code: response.status}
        }
      })
      .then((data) => {
        if (String(data.code) == '0') {
          /*打开支付宝进行支付*/
          Alipay.pay(data.result).then((data) => {
            if (data.length && data[0].resultStatus) {
              /*处理支付结果*/
              switch (data[0].resultStatus) {
                 case "9000":
                   opt.success && opt.success(data)
                   break;
                 case "8000":
                   opt.fail && opt.fail('支付结果未知,请查询订单状态')
                   break;
                 case "4000":
                   opt.fail && opt.fail('订单支付失败')
                   break;
                 case "5000":
                   opt.fail && opt.fail('重复请求')
                   break;
                 case "6001":
                   opt.fail && opt.fail('用户中途取消')
                   break;
                 case "6002":
                   opt.fail && opt.fail('网络连接出错')
                   break;
                 case "6004":
                   opt.fail && opt.fail('支付结果未知,请查询订单状态')
                   break;
                 default:
                   opt.fail && opt.fail('其他失败原因')
                   break;
               }
             } else {
               opt.fail && opt.fail('其他失败原因')
             }
           }, (err) => {
             opt.fail && opt.fail('支付失败,请重新支付')
           }
         )
       } else {
         opt.error && opt.error('支付参数错误')
       }
    })
  }
}