美文网首页react/react-native
react-native集成支付宝支付

react-native集成支付宝支付

作者: 冷宿Coder | 来源:发表于2018-11-20 18:05 被阅读141次

    前言

    RN支付宝需要分别对iOS(Xcode)和安卓(AS)配置,与原生app相比只是将支付操作放在了RN当中。

    流程大同小异,一般都是从后台获取支付字符串,然后传递支付字符串调用支付宝SDK,SDK再调用支付宝的支付模块。如果用户已安装支付宝App,会跳转到支付宝支付。如果用户没有安装支付宝App,商家App内会调起支付宝网页支付收银台,用户登录支付宝账户支付。

    支付宝SDK下载

    Android

    1.将alipaySdk-xxxxxxxx.jar包放入android/app/libs目录下,如下图。

    image

    2.在android/app/build.gradledependencies中查看是否引用了libs,若没有则添加,如下图。

    image

    3.在android/app/src/AndroidManifest.xml文件里面添加声明:

    <!-- 支付宝 activity 声明 -->
    <activity
     android:name="com.alipay.sdk.app.H5PayActivity"
     android:configChanges="orientation|keyboardHidden|navigation|screenSize"
     android:exported="false"
     android:screenOrientation="behind"
     android:windowSoftInputMode="adjustResize|stateHidden" >
    </activity>
    <activity
     android:name="com.alipay.sdk.app.H5AuthActivity"
     android:configChanges="orientation|keyboardHidden|navigation"
     android:exported="false"
     android:screenOrientation="behind"
     android:windowSoftInputMode="adjustResize|stateHidden" >
    </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" />
    

    4.在android/app/proguard-rules.pro添加混淆规则:

    # 支付
    -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 *;}
    -keep class com.alipay.sdk.app.H5PayCallback {
     <fields>;
     <methods>;
    }
    -keep class com.alipay.android.phone.mrpc.core.** { *; }
    -keep class com.alipay.apmobilesecuritysdk.** { *; }
    -keep class com.alipay.mobile.framework.service.annotation.** { *; }
    -keep class com.alipay.mobilesecuritysdk.face.** { *; }
    -keep class com.alipay.tscenter.biz.rpc.** { *; }
    -keep class org.json.alipay.** { *; }
    -keep class com.alipay.tscenter.** { *; }
    -keep class com.ta.utdid2.** { *;}
    -keep class com.ut.device.** { *;}
    

    5.android/app/src/main/java/com.xx下创建alipay,如下图。

    Android3.png

    6.创建AlipayModule.java,代码如下:

    package com.xxxx.alipay;
    
    import com.alipay.sdk.app.PayTask;
    import com.facebook.react.bridge.Arguments;
    import com.facebook.react.bridge.Promise;
    import com.facebook.react.bridge.ReactApplicationContext;
    import com.facebook.react.bridge.ReactContextBaseJavaModule;
    import com.facebook.react.bridge.ReactMethod;
    import com.facebook.react.bridge.WritableMap;
    import java.util.Map;
    
    public class AlipayModule extends ReactContextBaseJavaModule {
    
        public AlipayModule(ReactApplicationContext reactContext) {
            super(reactContext);
        }
    
        @Override
        public String getName() {
            return "Alipay";
        }
    
        @ReactMethod
        public void pay(final String orderInfo, final Promise promise) {
            Runnable payRunnable = new Runnable() {
                @Override
                public void run() {
                    WritableMap map = Arguments.createMap();
                    PayTask alipay = new PayTask(getCurrentActivity());
                    Map<String, String> result = alipay.payV2(orderInfo,true);
                    for (Map.Entry<String, String> entry: result.entrySet())
                        map.putString(entry.getKey(), entry.getValue());
                    promise.resolve(map);
                }
            };
            // 必须异步调用
            Thread payThread = new Thread(payRunnable);
            payThread.start();
        }
    
    }
    

    7.创建AlipayPackage.java,代码如下:

    package com.xxxx.alipay;
    
    import com.facebook.react.ReactPackage;
    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;
    
    public class AlipayPackage implements ReactPackage {
    
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
    
        @Override
        public List<NativeModule> createNativeModules(
                ReactApplicationContext reactContext) {
            List<NativeModule> modules = new ArrayList<>();
            modules.add(new AlipayModule(reactContext));
            return modules;
        }
    
    }
    

    8.在com.xxxx下的MainApplication中注册模块:

     @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
              new MainReactPackage(),
                  // ...other packages
               new AlipayPackage(), // <-- 注册支付宝支付模块
          );
        }
    

    iOS

    1.启动Xcode,把iOS包中的压缩文件中以下文件拷贝到项目文件夹下,并导入到项目工程中。
    AlipaySDK.bundle
    AlipaySDK.framework

    2.在Build Phases选项卡的Link Binary With Libraries中,确保增加了以下依赖库:


    iOS3.jpg

    3.在Xcode中打开项目,设置项目属性中的URL Schemes为你支付宝开放平台对此App设置的唯一标识。如图标红位置所示:


    wx3.jpg

    4.在项目目录下创建Group Alipay,并创建RCTAlipay模块,如下图所示:

    ios2.jpg
    5.编写RCTAlipay.h代码如下:
    #import <Foundation/Foundation.h>
    #import <React/RCTBridgeModule.h>
    #import <UIKit/UIKit.h>
    #import <AlipaySDK/AlipaySDK.h>
    
    @interface RCTAlipay : NSObject<RCTBridgeModule>
    
    +(void) handleCallback:(NSURL *)url;
    
    @end
    
    

    6.编写RCTAlipay.m代码如下:

    #import "RCTAlipay.h"
    
    static RCTPromiseResolveBlock _resolve;
    static RCTPromiseRejectBlock _reject;
    
    @implementation RCTAlipay
    
    RCT_EXPORT_MODULE();
    
    RCT_REMAP_METHOD(pay, payInfo:(NSString *)payInfo resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
    {
      NSArray *urls = [[NSBundle mainBundle] infoDictionary][@"CFBundleURLTypes"];
      NSMutableString *appScheme = [NSMutableString string];
      BOOL multiUrls = [urls count] > 1;
      for (NSDictionary *url in urls) {
        NSArray *schemes = url[@"CFBundleURLSchemes"];
        if (!multiUrls ||
            (multiUrls && [@"alipay" isEqualToString:url[@"CFBundleURLName"]])) {
          [appScheme appendString:schemes[0]];
          break;
        }
      }
      
      if ([appScheme isEqualToString:@""]) {
        NSString *error = @"scheme cannot be empty";
        reject(@"10000", error, [NSError errorWithDomain:error code:10000 userInfo:NULL]);
        return;
      }
      
      _resolve = resolve;
      _reject = reject;
      
      
      [[AlipaySDK defaultService] payOrder:payInfo fromScheme:appScheme callback:^(NSDictionary *resultDic) {
        [RCTAlipay handleResult:resultDic];
      }];
    }
    
    +(void) handleResult:(NSDictionary *)resultDic
    {
      NSString *status = resultDic[@"resultStatus"];
      if ([status integerValue] >= 8000) {
        _resolve(@[resultDic]);
      } else {
        _reject(status, resultDic[@"memo"], [NSError errorWithDomain:resultDic[@"memo"] code:[status integerValue] userInfo:NULL]);
      }
    }
    
    +(void) handleCallback:(NSURL *)url
    {
      //如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开发包
      if ([url.host isEqualToString:@"safepay"]) {
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
          //【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
          [self handleResult:resultDic];
        }];
      }
      if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回authCode
        
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
          //【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
          [self handleResult:resultDic];
        }];
      }
    }
    
    @end
    

    7.【重要】此时iOS的调起支付宝网页支付(即未安装支付宝App)在RN中可以实现支付完成返回App进行相关操作,但是调起支付宝App支付完成后会发现相关支付完成的操作失效,所以要在Appdelegate.m中导入RCTAlipay.h进行相关回调:

    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options {
      //如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开发包
      if ([url.host isEqualToString:@"safepay"]) {
          [RCTAlipay handleCallback:url];
        return YES;
      }
     
      return  YES;
    }
    

    react-native

    1.编写Alipay.js工具类

    import { NativeModules } from 'react-native';
    export default NativeModules.Alipay;
    

    2.在支付页面调用Alipay发起支付宝支付:

    import Alipay from './Alipay'
     async aliPayAction(payStr){
           //payStr为从后台获取的支付字符串
            Alipay.pay(payStr).then((data) =>{
               let resultDic = {};
    /*笔者iOS端和安卓端返回的支付回调结果数据不一致,可能和支付宝sdk版本有关,
    读者可自行根据返回数据进行相关处理,iOS(RCTAlipay.m)和安卓(AlipayModule)
    可自行选择需要resolve回调判断处理的数据,如只返回resultStatus*/
                if (Platform.OS === 'ios'){
                    resultDic = data[0];
                } else {
                    resultDic = data;
                }
                if (resultDic.resultStatus == '9000'){
                    //支付成功
                }else {
                    //支付失败
                }
            }).catch((err) => {
                console.log('err='+err);
                this.refs.toast.show('支付失败');
            });
        }
    

    至此react-native支付宝支付集成完成,笔者第一次集成的时候也是借鉴了他人的方法,本文算是对整个集成过程的回顾和优化,与君共勉。

    相关文章

      网友评论

        本文标题:react-native集成支付宝支付

        本文链接:https://www.haomeiwen.com/subject/appxqqtx.html