Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement BillingOptions for ApplePay #252

Open
wants to merge 3 commits into
base: release/express-checkout-beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ target 'example_0_70_6' do
)

pod 'primer-io-react-native', :path => '../../sdk'
pod 'PrimerSDK', '2.32.0-express-checkout.1'
pod 'PrimerSDK', :git => 'https://github.com/primer-io/primer-sdk-ios.git', :branch => 'bn/feature/ACC-4508-Expose-ApplePay-Shipping-Options'
pod 'Primer3DS'
pod 'PrimerIPay88MYSDK'
pod 'PrimerKlarnaSDK', '1.1.1'
Expand Down
33 changes: 20 additions & 13 deletions packages/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ PODS:
- ReactCommon/turbomodule/core (= 0.72.0)
- fmt (6.2.1)
- glog (0.3.5)
- primer-io-react-native (2.27.0):
- PrimerSDK (= 2.31.0)
- primer-io-react-native (2.28.0-beta.1):
- PrimerSDK
- React-Core
- Primer3DS (2.3.2)
- Primer3DS (2.4.0)
- PrimerIPay88MYSDK (0.1.7)
- PrimerKlarnaSDK (1.1.1)
- PrimerSDK (2.31.0):
- PrimerSDK/Core (= 2.31.0)
- PrimerSDK/Core (2.31.0)
- PrimerSDK (2.31.3):
- PrimerSDK/Core (= 2.31.3)
- PrimerSDK/Core (2.31.3)
- PrimerStripeSDK (1.0.0)
- RCT-Folly (2021.07.22.00):
- boost
Expand Down Expand Up @@ -416,7 +416,7 @@ DEPENDENCIES:
- Primer3DS
- PrimerIPay88MYSDK
- PrimerKlarnaSDK (= 1.1.1)
- PrimerSDK
- PrimerSDK (from `https://github.com/primer-io/primer-sdk-ios.git`, branch `bn/feature/ACC-4508-Expose-ApplePay-Shipping-Options`)
- PrimerStripeSDK (= 1.0.0)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
Expand Down Expand Up @@ -462,7 +462,6 @@ SPEC REPOS:
- Primer3DS
- PrimerIPay88MYSDK
- PrimerKlarnaSDK
- PrimerSDK
- PrimerStripeSDK
- SocketRocket

Expand All @@ -479,6 +478,9 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
primer-io-react-native:
:path: "../../sdk"
PrimerSDK:
:branch: bn/feature/ACC-4508-Expose-ApplePay-Shipping-Options
:git: https://github.com/primer-io/primer-sdk-ios.git
RCT-Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
RCTRequired:
Expand Down Expand Up @@ -552,18 +554,23 @@ EXTERNAL SOURCES:
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"

CHECKOUT OPTIONS:
PrimerSDK:
:commit: 677b98e205ca62a28f67940e2f4fe39bcef6c855
:git: https://github.com/primer-io/primer-sdk-ios.git

SPEC CHECKSUMS:
boost: 57d2868c099736d80fcd648bf211b4431e51a558
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: bb17efca94c43508cbe54fb0a35e36df30da5213
FBReactNativeSpec: 6e7e74b1ed7f0a1a469a82a67521b33285f5fef3
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
primer-io-react-native: 4b4eb3b62c7787537191a6f74598db8a78c29587
Primer3DS: 81e7969033230c7346a517cd609be956914738bb
primer-io-react-native: a1692a02390c4b80b185f39c291cc0b54da8509b
Primer3DS: 0cd588a22e3c3c89fbbced8b252f5fab187a9ba1
PrimerIPay88MYSDK: 436ee0be7e2c97e4e81456ccddee20175e9e3c4d
PrimerKlarnaSDK: 564105170cc7b467bf95c31851813ea41c468f8b
PrimerSDK: 78d1a48ba9b4677f78da9750448af6c72007f4fe
PrimerSDK: 97197b708f58d992aaa40163bc3f3ba58fa8a2e6
PrimerStripeSDK: c37d4e7c1b5256d67d4890c4cc4b38ddc9427489
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
RCTRequired: 656ef0536dd60a9740961ade6a64ba0cb0572d2b
Expand Down Expand Up @@ -603,6 +610,6 @@ SPEC CHECKSUMS:
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 1d6727ed193122f6adaf435c3de1a768326ff83b

PODFILE CHECKSUM: 4505e915c8982e98dcb8297a1c627233ce3a067f
PODFILE CHECKSUM: e51ec02f6773a88bef8a0c92c8d7392c389ab0c3

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
100 changes: 50 additions & 50 deletions packages/example/ios/example_0_70_6.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

This file was deleted.

3 changes: 2 additions & 1 deletion packages/example/src/screens/CheckoutScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ const CheckoutScreen = (props: any) => {
isCaptureBillingAddressEnabled: true,
showApplePayForUnsupportedDevice: true,
checkProvidedNetworks: false,
shippingOptions: appPaymentParameters.shippingOptions
shippingOptions: appPaymentParameters.shippingOptions,
billingOptions: appPaymentParameters.billingOptions
},
googlePayOptions: {
isCaptureBillingAddressEnabled: true,
Expand Down
142 changes: 116 additions & 26 deletions packages/example/src/screens/SettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ export interface AppPaymentParameters {
clientSessionRequestBody: IClientSessionRequestBody;
merchantName?: string;
shippingOptions?: {
isCaptureShippingAddressEnabled: boolean;
requireShippingMethod: boolean;
additionalShippingContactFields: string[];
shippingContactFields: string[];
};
billingOptions?: {
requiredBillingContactFields: string[];
};
}

Expand Down Expand Up @@ -72,10 +74,12 @@ const SettingsScreen = ({ navigation }) => {
const [visaSurcharge, setVisaSurcharge] = React.useState<number | undefined>(appPaymentParameters.clientSessionRequestBody.paymentMethod?.options?.PAYMENT_CARD?.networks.VISA?.surcharge.amount);
const [masterCardSurcharge, setMasterCardSurcharge] = React.useState<number | undefined>(appPaymentParameters.clientSessionRequestBody.paymentMethod?.options?.PAYMENT_CARD?.networks.MASTERCARD?.surcharge.amount);

const [isBillingOptionsApplied, setIsBillingOptionsApplied] = useState<boolean>(false);
const [requiredBillingContactFields, setRequiredBillingContactFields] = useState<string[]>([]);

const [isShippingOptionsApplied, setIsShippingOptionsApplied] = useState<boolean>(false);
const [isCaptureShippingAddressEnabled, setIsCaptureShippingAddressEnabled] = useState<boolean>(false);
const [requireShippingMethod, setRequireShippingMethod] = useState<boolean>(false);
const [additionalShippingContactFields, setAdditionalShippingContactFields] = useState<string[]>([]);
const [shippingContactFields, setShippingContactFields] = useState<string[]>([]);

const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.black : Colors.white
Expand Down Expand Up @@ -628,6 +632,7 @@ const SettingsScreen = ({ navigation }) => {
{renderMerchantSection()}
{renderCustomerSection()}
{renderSurchargeSection()}
{renderBillingOptionsSection()}
{renderShippingOptionsSection()}
</View>
);
Expand Down Expand Up @@ -686,6 +691,86 @@ const SettingsScreen = ({ navigation }) => {
);
}

const renderBillingOptionsSection = () => {
return (
<View style={{ marginTop: 12, marginBottom: 8 }}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ ...styles.heading1, marginBottom: 4 }}>
Billing Options
</Text>
<View style={{ flex: 1 }} />
<Switch
value={isBillingOptionsApplied}
onValueChange={val => {
setIsBillingOptionsApplied(val);
}}
/>
</View>

{
!isBillingOptionsApplied ? null :
<View>
<Text style={{ ...styles.heading2, marginVertical: 4 }}>Billing Contact Fields</Text>
<View style={{ marginVertical: 4 }}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Name</Text>
<Switch
value={requiredBillingContactFields.includes('name')}
onValueChange={val => {
if (val) {
setRequiredBillingContactFields([...requiredBillingContactFields, 'name']);
} else {
setRequiredBillingContactFields(requiredBillingContactFields.filter(field => field !== 'name'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Email Address</Text>
<Switch
value={requiredBillingContactFields.includes('emailAddress')}
onValueChange={val => {
if (val) {
setRequiredBillingContactFields([...requiredBillingContactFields, 'emailAddress']);
} else {
setRequiredBillingContactFields(requiredBillingContactFields.filter(field => field !== 'emailAddress'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Phone Number</Text>
<Switch
value={requiredBillingContactFields.includes('phoneNumber')}
onValueChange={val => {
if (val) {
setRequiredBillingContactFields([...requiredBillingContactFields, 'phoneNumber']);
} else {
setRequiredBillingContactFields(requiredBillingContactFields.filter(field => field !== 'phoneNumber'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Postal Address</Text>
<Switch
value={requiredBillingContactFields.includes('postalAddress')}
onValueChange={val => {
if (val) {
setRequiredBillingContactFields([...requiredBillingContactFields, 'postalAddress']);
} else {
setRequiredBillingContactFields(requiredBillingContactFields.filter(field => field !== 'postalAddress'));
}
}}
/>
</View>
</View>
</View>
}
</View>
);
};

const renderShippingOptionsSection = () => {
return (
<View style={{ marginTop: 12, marginBottom: 8 }}>
Expand All @@ -705,15 +790,6 @@ const SettingsScreen = ({ navigation }) => {
{
!isShippingOptionsApplied ? null :
<View>
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}>
<Text style={{ flex: 1 }}>Capture Shipping Address Enabled</Text>
<Switch
value={isCaptureShippingAddressEnabled}
onValueChange={val => {
setIsCaptureShippingAddressEnabled(val);
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', marginVertical: 4 }}>
<Text style={{ flex: 1 }}>Require Shipping Method</Text>
<Switch
Expand All @@ -723,43 +799,56 @@ const SettingsScreen = ({ navigation }) => {
}}
/>
</View>
<Text style={{ ...styles.heading2, marginVertical: 4 }}>Additional Shipping Contact Fields</Text>
<Text style={{ ...styles.heading2, marginVertical: 4 }}>Shipping Contact Fields</Text>
<View style={{ marginVertical: 4 }}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Name</Text>
<Switch
value={additionalShippingContactFields.includes('name')}
value={shippingContactFields.includes('name')}
onValueChange={val => {
if (val) {
setAdditionalShippingContactFields([...additionalShippingContactFields, 'name']);
setShippingContactFields([...shippingContactFields, 'name']);
} else {
setAdditionalShippingContactFields(additionalShippingContactFields.filter(field => field !== 'name'));
setShippingContactFields(shippingContactFields.filter(field => field !== 'name'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Email Address</Text>
<Switch
value={additionalShippingContactFields.includes('emailAddress')}
value={shippingContactFields.includes('emailAddress')}
onValueChange={val => {
if (val) {
setAdditionalShippingContactFields([...additionalShippingContactFields, 'emailAddress']);
setShippingContactFields([...shippingContactFields, 'emailAddress']);
} else {
setAdditionalShippingContactFields(additionalShippingContactFields.filter(field => field !== 'emailAddress'));
setShippingContactFields(shippingContactFields.filter(field => field !== 'emailAddress'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Phone Number</Text>
<Switch
value={additionalShippingContactFields.includes('phoneNumber')}
value={shippingContactFields.includes('phoneNumber')}
onValueChange={val => {
if (val) {
setShippingContactFields([...shippingContactFields, 'phoneNumber']);
} else {
setShippingContactFields(shippingContactFields.filter(field => field !== 'phoneNumber'));
}
}}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 1 }}>Postal Address</Text>
<Switch
value={shippingContactFields.includes('postalAddress')}
onValueChange={val => {
if (val) {
setAdditionalShippingContactFields([...additionalShippingContactFields, 'phoneNumber']);
setShippingContactFields([...shippingContactFields, 'postalAddress']);
} else {
setAdditionalShippingContactFields(additionalShippingContactFields.filter(field => field !== 'phoneNumber'));
setShippingContactFields(shippingContactFields.filter(field => field !== 'postalAddress'));
}
}}
/>
Expand Down Expand Up @@ -877,11 +966,12 @@ const SettingsScreen = ({ navigation }) => {

appPaymentParameters.clientSessionRequestBody = currentClientSessionRequestBody;
appPaymentParameters.shippingOptions = isShippingOptionsApplied ? {
isCaptureShippingAddressEnabled: isCaptureShippingAddressEnabled,
requireShippingMethod: requireShippingMethod,
additionalShippingContactFields: additionalShippingContactFields,
shippingContactFields: shippingContactFields,
} : undefined;
appPaymentParameters.billingOptions = isBillingOptionsApplied ? {
requiredBillingContactFields: requiredBillingContactFields,
} : undefined;

}

return (
Expand Down
Loading