iamport / iamport-react-native

React Native용 아임포트 일반.결제 및 휴대폰 본인인증 모듈입니다.
MIT License
165 stars 62 forks source link

카카오페이 결제 이후 써드파티에서 본 앱으로 복귀하지 못하고 카카오톡으로 가지네요 #170

Open nogal2 opened 2 years ago

nogal2 commented 2 years ago

정확하게는 카카오페이 결제 이후 써드파티에서 '완료'를 누르면 본 앱으로 복귀하지 못하고 카카오톡으로 가지네요 테스트용입니다. 카카오톡으로 가지고 난 후 본 앱을 다시 실행하면 navigate한 곳으로 이동해 있습니다. PaymentResult.tsx 화면으로여. 써드파티에서 다시 본앱으로는 안되는걸까요?

package.json -> dependencies "@react-native-picker/picker": "^2.4.1", "@react-navigation/bottom-tabs": "^6.3.1", "@react-navigation/native": "^6.0.10", "@react-navigation/native-stack": "^6.6.2", "axios": "^0.24.0", "iamport-react-native": "^2.0.1", "qs": "^6.10.3", "react": "17.0.2", "react-native": "0.66.4", "react-native-calendars": "^1.1284.0", "react-native-safe-area-context": "^4.2.5", "react-native-screens": "^3.13.1", "react-native-webview": "^11.17.2"

코드 공유합니다. 여기에 있는 example과 거의 똑같이 했습니다.

import { NavigationProp, RouteProp, useNavigation, useRoute } from "@react-navigation/native"; import IMP from "iamport-react-native"; import React from "react"; import { SafeAreaView, } from "react-native"; import Loading from "../pages/Loading"; import { StackParamList } from "../pages/PaymentsNavigator"; import { getUserCode } from "../utils";

const Payments = () => {

const navigation = useNavigation<NavigationProp<StackParamList>>();
const route = useRoute<RouteProp<StackParamList>>();
const params = route.params?.params;
const tierCode = route.params?.tierCode;
const userCode = getUserCode(params!.pg, tierCode);

return (
    <SafeAreaView style={{flex:1, justifyContent:'center'}}>
        <IMP.Payment 
            userCode={userCode}
            tierCode={tierCode}
            loading={<Loading />}
            data={params!}
            callback={(response) => navigation.navigate('PaymentsResult', response)}
        />
    </SafeAreaView>
)

}

export default Payments;

import { NavigationProp, useNavigation } from "@react-navigation/native"; import { IMPConst } from "iamport-react-native"; import React, { useState } from "react"; import { KeyboardAvoidingView, Platform, Pressable, SafeAreaView, ScrollView, StyleSheet, Switch, Text, TextInput, View } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { PaymentsParams, StackParamList } from "../pages/PaymentsNavigator"; import { getMethods, getQuotas, PGS, TIER_CODES } from "../utils"; import CustomPicker from "./CustomPicker";

const PaymentsTest = () => { const navigation = useNavigation<NavigationProp>(); const [pg, setPg] = useState('html5inicis'); const [tierCode, setTierCode] = useState(undefined); const [method, setMethod] = useState('card'); const [cardQuota, setCardQuota] = useState(0); const [merchantUid, setMerchantUid] = useState(`mid${new Date().getTime()}`); const [name, setName] = useState('아임포트 결제데이터분석'); const [amount, setAmount] = useState('39000'); const [buyerName, setBuyerName] = useState('홍길동'); const [buyerTel, setBuyerTel] = useState('01012341234'); const [buyerEmail, setBuyerEmail] = useState('example@example.com'); const [vbankDue, setVbankDue] = useState(''); const [bizNum, setBizNum] = useState(''); const [escrow, setEscrow] = useState(false); const [digital, setDigital] = useState(false); console.log(method) const insets = useSafeAreaInsets();

return (
    <SafeAreaView style={[styles.container, {flex:1, paddingTop: -insets.top}]}>
        <KeyboardAvoidingView
            contentContainerStyle={{flex:1}}
            behavior={Platform.OS === 'ios' ? 'padding' : undefined}
            keyboardVerticalOffset={Platform.OS === 'ios' ? 95 : undefined}
        >
            <ScrollView style={{backgroundColor:'#fff'}}>
                <View style={[styles.form]}>
                    <View>
                        <Text style={[styles.formText]}>PG사</Text>
                    </View>
                    <CustomPicker 
                        data={PGS}
                        selectValue={pg}
                        onValueChange={(value) => {
                            setPg(value);
                            const methods = getMethods(value);
                            setMethod(methods[0].value);
                        }}
                    />
                    <View>
                        <Text style={[styles.formText]}>티어코드</Text>
                    </View>
                    <CustomPicker 
                        data={TIER_CODES}
                        selectValue={tierCode}
                        onValueChange={(value) => setTierCode(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>결제수단</Text>
                    </View>
                    <CustomPicker
                        data={getMethods(pg)}
                        selectValue={method}
                        onValueChange={(value) => setMethod(value)}
                    />
                    {method === 'card' && (
                        <>
                        <View>
                            <Text style={[styles.formText]}>할부개월수</Text>
                        </View>
                        <CustomPicker 
                            data={getQuotas(pg)}
                            selectValue={cardQuota}
                            onValueChange={(value) => setCardQuota(parseInt(value, 10))}
                        />
                        </>
                    )}
                    {method === 'vbank' && (
                         <>
                         <View>
                            <Text style={[styles.formText]}>입금기한</Text>
                         </View>
                         <TextInput 
                            style={[styles.formTextInput, {flex:1}]}
                            value={vbankDue}
                            onChangeText={(value) => setVbankDue(value)}
                         />
                         </>
                    )}
                    {method === 'vbank' && pg === 'danal_tpay' && (
                        <>
                        <View>
                            <Text style={[styles.formText]}>사업자번호</Text>
                        </View>
                        <TextInput 
                            style={[styles.formTextInput, {flex:1}]}
                            value={bizNum}
                            onChangeText={(value) => setBizNum(value)}
                        />
                        </>
                    )}
                    {method === 'phone' && (
                        <>
                        <View>
                            <Text style={[styles.formText]}>실물컨텐츠</Text>
                        </View>
                        <Switch 
                            style={[styles.formSwitch]}
                            value={digital}
                            onValueChange={(value) => setDigital(value)}
                        />
                        </>
                    )}
                    <View>
                        <Text style={[styles.formText]}>에스크로</Text>
                    </View>
                    <Switch 
                        style={[styles.formSwitch]}
                        value={escrow}
                        onValueChange={(value) => setEscrow(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>주문명</Text>
                    </View>
                    <TextInput 
                        style={[styles.formTextInput, {flex:1}]}
                        value={name}
                        onChangeText={(value) => setName(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>결제금액</Text>
                    </View>
                    <TextInput
                        style={[styles.formTextInput, {flex:1}]}
                        value={amount}
                        keyboardType="number-pad"
                        returnKeyType={'done'}
                        onChangeText={(value) => setAmount(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>주문번호</Text>
                    </View>
                    <TextInput 
                        style={[styles.formTextInput, {flex:1}]}
                        value={merchantUid}
                        onChangeText={(value) => setMerchantUid(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>이름</Text>
                    </View>
                    <TextInput 
                        style={[styles.formTextInput, {flex:1}]}
                        value={buyerName}
                        onChangeText={(value) => setBuyerName(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>전화번호</Text>
                    </View>
                    <TextInput 
                        style={[styles.formTextInput, {flex:1}]}
                        value={buyerTel}
                        keyboardType="number-pad"
                        returnKeyType={'done'}
                        onChangeText={(value) => setBuyerTel(value)}
                    />
                    <View>
                        <Text style={[styles.formText]}>이메일</Text>
                    </View>
                    <TextInput 
                        style={[styles.formTextInput, {flex:1}]}
                        value={buyerEmail}
                        onChangeText={(value) => setBuyerEmail(value)}
                    />
                    <Pressable
                        style={[styles.pressable]}
                        onPress={() => {
                            const data: PaymentsParams = {
                                params: {
                                    pg,
                                    pay_method: method,
                                    currency: undefined,
                                    notice_url: undefined,
                                    display: undefined,
                                    merchant_uid: merchantUid,
                                    name,
                                    amount,
                                    app_scheme: 'exampleforrn',
                                    tax_free: undefined,
                                    buyer_name: buyerName,
                                    buyer_tel: buyerTel,
                                    buyer_email: buyerEmail,
                                    buyer_addr: undefined,
                                    buyer_postcode: undefined,
                                    custom_data: undefined,
                                    vbank_due: undefined,
                                    digital: undefined,
                                    language: undefined,
                                    biz_num: undefined,
                                    customer_uid: undefined,
                                    naverPopupMode: undefined,
                                    naverUseCfm: undefined,
                                    m_redirect_url: IMPConst.M_REDIRECT_URL,
                                    niceMobileV2: true,
                                    escrow,
                                },
                                tierCode,
                            };

                            // 신용카드의 경우, 할부기한 추가
                            if (method === 'card' && cardQuota !== 0) {
                                data.params.display = {
                                    card_quota: cardQuota === 1 ? [] : [cardQuota]
                                };
                            }

                            // 가상계좌의 경우, 입금기한 추가
                            if (method === 'vbank' && vbankDue) {
                                data.params.vbank_due = vbankDue;
                            }

                            // 다날 && 가상계좌의 경우, 사업자 등록번호 10자리 추가
                            if (method === 'vbank' && pg === 'danal_tpay') {
                                data.params.biz_num = bizNum;
                            }

                            // 휴대폰 소액결제의 경우, 실물 컨텐츠 여부 추가
                            if (method === 'phone') {
                                data.params.digital = digital;
                            }

                            // 정기결제의 경우, customer_uid 추가
                            if (method === 'phone') {
                                data.params.digital = digital;
                            }

                            if (pg === 'naverpay') {
                                const today = new Date();
                                const oneMonthLater = new Date(
                                    today.setMonth(today.getMonth() + 1)
                                );
                                const dd = String(oneMonthLater.getDate()).padStart(2, '0');
                                const mm = String(oneMonthLater.getMonth() + 1).padStart(2, '0');
                                const yyyy = oneMonthLater.getFullYear();

                                data.params.naverPopupMode = false;
                                data.params.naverUseCfm = `${yyyy}${mm}${dd}`;
                                data.params.naverProducts = [
                                    {
                                        categoryType: 'BOOK',
                                        categoryId: 'GENERAL',
                                        uid: '107922211',
                                        name: '한국사',
                                        payReferrer: 'NAVER_BOOK',
                                        count: 10,
                                    },
                                ];
                            }
                            navigation.navigate('Payments', data);
                        }}
                    >
                        <Text style={{fontWeight:'bold', color:'#fff'}}>결제하기</Text>

                    </Pressable>
                </View>
            </ScrollView>

        </KeyboardAvoidingView>
    </SafeAreaView>
);

};

export default PaymentsTest;

nogal2 commented 2 years ago

방금 다시 하니 또 되네요. 이게 됐다가 안됐다가 하는데, 확인 부탁드립니다 :)

anymate98 commented 2 years ago

안녕하세요. 혹시 문제가 발생하는 곳이 ios인가요?

nogal2 commented 2 years ago

아 ios는 제 폰이 아니라 확인까지는 못했고, 안드로이드 카카오페이 한정해서 그렇습니다.

anymate98 commented 2 years ago

네 이쪽에서 확인해보고 결과 알려드리겠습니다.

anymate98 commented 2 years ago

혹시 "써드파티"의 뜻이 정확이 무엇인지 알 수 있을까요? 또 문제가 되는 과정이 본앱 -> 써드파티 -> 카카오톡 ->(수동)-> 본앱 이 맞나요?

nogal2 commented 2 years ago

본앱에서 카카오 결제로 가고 거기서 결제 완료 화면이 한번더 화면이 옮겨져서 써드파티라고 명명하였고, 본앱 -> 카카오 페이 결제 "다음" 버튼 누르는 화면 => "결제하기" 버튼 화면(금액과 pay머니가 나오는) => '확인'버튼 누르는 화면 에서 '확인'을 누르면 본 앱으로 돌아가져야 하는데, 카카오톡 화면으로 가진다는 뜻이었습니다. 이게 PaymentResult 화면으로 가질 때도 있고, 카카오톡 화면으로 가질 때도 있어서, 원인이 뭔지 모르겠어서요.

nogal2 commented 2 years ago

의도적으로 카카오톡 앱으로 간 적은 없고, 순서대로 사진 올려드릴게요. KakaoTalk_Photo_2022-06-10-18-44-22 001 '결제 테스트 클릭'

KakaoTalk_Photo_2022-06-10-18-44-22 002 '결제하기' 클릭(카카오페이로 선택했습니다)

KakaoTalk_Photo_2022-06-10-18-44-22 003 '다음' 클릭

KakaoTalk_Photo_2022-06-10-18-44-22 004 '테스트 결제하기' 클릭

KakaoTalk_Photo_2022-06-10-18-44-22 005 '확인' 클릭

KakaoTalk_Photo_2022-06-10-18-44-22 006 '확인'클릭

하면 카카오톡 으로 가지네요.

방금 캡처하면서 될 때와 안 될 때의 차이를 알아냈는데 스마트폰에서 카카오톡을 실행시킨뒤, 본 앱을 실행해서 카카오페이 후 위와 같은 순서로 진행하면 본 앱으로 가는게 아니라 카카오톡으로 가지고 카카오톡이 꺼져있을시(스마트폰 내에서 강제종료)에 할 때는 본 앱으로 돌아옵니다.

anymate98 commented 2 years ago

스크린샷 감사합니다. 이미지의 비율로 보아 아마 폴드를 사용하시는 것 같은데 저희측에서도 폴드에서만 이 문제가 확인되었기 때문에 폴드 특유의 현상이라고 보여집니다. 다른 안드로이드 폰에서 시도해보시고 재현이 되는지 확인 부탁드리겠습니다.