Skip to content

【React-Native】Stripe 支付 #11

@famousczm

Description

@famousczm

需求描述

项目需要接入支付功能,并要支持支付宝支付信用卡支付,之前的项目有维护过这块功能,但是是前人写的,只能有个大概的理解,通过这次接手,可以重新学习一下。

准备工作

Stripe 是什么

Stripe是一家提供讓個人或公司在網際網路上接受付款服務的科技公司。Stripe提供在網上接受付款所需的技術、避免信用卡詐騙技術及銀行基礎設施 ----- 维基百科

Stripe 提供了很便利的支付服务,而且文档也写得很详细,就是没中文。关于注册申请 KEY 之类的流程略过,要拿到这个 KEY 作为客户端与 Stripe 通信的一个凭证。

Stripe Docs 入口

IOS接入

  1. 首先是下载 Stripe iOS SDK,我是通过 CocoaPods 的方式接入:
pod 'Stripe'

然后 pod install 就好

  1. 在 AppDelegate 中配置拿到的 Stripe API Keys
#import "AppDelegate.h"
@import Stripe;

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[STPPaymentConfiguration sharedConfiguration] setPublishableKey:STRAP_KEY];
    // do any other necessary launch configuration
    return YES;
}
@end
  1. 配置信用卡支付
    信用卡支付我选择使用 Stripe 提供的 STPPaymentCardTextField 组件,就一输入框,能引导用户输入支付需要的数据,还能自动识别卡的类型和判断信息格式是否正确,省去不少功夫。效果如下:

代码如下:

// STPPaymentCardTextFieldView.m
#import <Foundation/Foundation.h>
#import "STPPaymentCardTextFieldView.h"

@interface STPPaymentCardTextFieldView ()

@end

@implementation STPPaymentCardTextFieldView

- (instancetype)init {
  if ((self = [super init])) {
  }
  return self;
}

- (void)getPayToken {
  __weak STPPaymentCardTextFieldView *_weakSelf = self;
  [[STPAPIClient sharedClient] createTokenWithCard:self.cardParams completion:^(STPToken *token, NSError *error) {
    if (token == nil || error != nil) {
      if (_weakSelf.onPayed) {
        _weakSelf.onPayed(@{@"result": @"fail"});
      }
    } else {
      if (_weakSelf.onPayed) {
        _weakSelf.onPayed(@{@"result": @"success",
                            @"stripeToken": [token tokenId],
                            @"type": @"card"});
      }
    }
  }];
}

@end
// RNTSTPPaymentCardTextFieldManager.m
#import "RNTSTPPaymentCardTextFieldManager.h"
#import "STPPaymentCardTextFieldView.h"

@interface RNTSTPPaymentCardTextFieldManager ()

@property(nonatomic, strong) STPPaymentCardTextFieldView *indicator;

@end

@implementation RNTSTPPaymentCardTextFieldManager

RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(onPayed, RCTBubblingEventBlock)

RCT_EXPORT_METHOD(getPayToken)
{
  if (self.indicator != NULL) {
    [self.indicator getPayToken];
  }
}

- (UIView *)view {
  //
  if (self.indicator == NULL) {
    self.indicator = [[STPPaymentCardTextFieldView alloc]init];
    self.indicator.delegate = self;
  }
  
  return self.indicator;
}

@end

STPPaymentCardTextFieldView 组件只写了一个 getPayToken 方法,当用户输入完卡信息点击去支付时调用,主要作用是将收集到的卡信息组合成 STPCardParams 实例,再通过 STPAPIClient 的 createTokenWithCard 方法生成 STPToken 实例通过事件的方式传回到 ReactNative 并发送给后端服务器,告知前端支付流程已结束。

Android接入

  1. 先下载 Stripe Android SDK:
implementation 'com.stripe:stripe-android:6.1.2'
  1. 配置信用卡支付
    选一个合适的用来收集卡信息的组件
    如果是跟 ios STPPaymentCardTextField 组件同样样式的话,就使用 CardInputWidget,还有一种是 CardMultilineWidget 多个输入框的,效果如下:

这里我遇到一个问题是 **CardInputWidget** 在输入完卡号之后不会自动跳转到输入 有效期和 CVC 信息,这好像是官方 bug,目前还没有修复,所以我选择了 **CardInputWidget**

相关issue

组件部分代码如下:

package com.test.pay.extend.component;

import android.support.annotation.Nullable;

import com.test.pay.commons.Constants;
import com.test.pay.extend.packager.STPPaymenetPackage;
import com.facebook.react.bridge.Arguments;
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 com.facebook.react.modules.core.DeviceEventManagerModule;
import com.stripe.android.Stripe;
import com.stripe.android.TokenCallback;
import com.stripe.android.model.Card;
import com.stripe.android.model.Token;
import com.stripe.android.view.CardMultilineWidget;

public class ReactPaymentCardTextFieldManager extends ReactContextBaseJavaModule {

    private ReactApplicationContext mContext;

    public ReactPaymentCardTextFieldManager(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
    }

    @Override
    public String getName() {
        return "RNTSTPPaymentCardTextFieldManager";
    }

    @ReactMethod
    public void getPayToken() {
        CardMultilineWidget cardMultilineWidget = STPPaymenetPackage.mReactSTPPaymentCardTextFieldManager.getCardMultilineWidget();
        if (cardMultilineWidget == null) {
            return;
        }
        final WritableMap params = Arguments.createMap();
        final Card cardToSave = cardMultilineWidget.getCard();
        if (cardToSave != null) {
            Stripe stripe = new Stripe(mContext, Constants.STP_PAYMENET_KEY);
            stripe.createToken(cardToSave, new TokenCallback() {

                @Override
                public void onError(Exception error) {
                    params.putString("result", "fail");
                    ReactPaymentCardTextFieldManager.this.sendEvent("onPayed", params);
                }

                @Override
                public void onSuccess(Token token) {
                    params.putString("result", "success");
                    params.putString("stripeToken", token.getId());
                    params.putString("type", "card");
                    ReactPaymentCardTextFieldManager.this.sendEvent("onPayed", params);
                }
            });
        } else {
            params.putString("result", "fail");
            ReactPaymentCardTextFieldManager.this.sendEvent("onPayed", params);
        }
    }

    private void sendEvent(String eventName,
                           @Nullable WritableMap params) {
        mContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, params);
    }

}

getPayToken 方法收集卡信息并生产 STPToken,流程和 ios 一样,然后通过事件的方式传送到 ReactNative。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions