Skip to content

Commit 7cb3aaa

Browse files
authored
Merge pull request #10 from MadBrains/processing_response
[2.1.0] Add new PaymentResponse
2 parents c6cf2ff + 32a17f5 commit 7cb3aaa

24 files changed

+337
-90
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.1.0
2+
3+
* `processingPayment` method returns raw payment data
4+
15
## 2.0.4
26

37
* Change proto structure

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Easy integration with Google Pay and Apple Pay for your flutter app.
1717
Add this to your package's pubspec.yaml file:
1818
```yaml
1919
dependencies:
20-
mad_pay: 2.0.4
20+
mad_pay: 2.1.0
2121
```
2222
2323
For Android: set `minSdkVersion` to 21

android/src/main/kotlin/ru/madbrains/mad_pay/Constants.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ const val LOAD_PAYMENT_DATA_REQUEST_CODE = 991
44

55
const val CHANNEL = "mad_pay"
66

7-
const val TOKEN = "token"
8-
97
const val PAYMENT = "payment"
108
const val CHECK_PAYMENTS = "checkPayments"
119
const val CHECK_ACTIVE_CARD = "checkActiveCard"

android/src/main/kotlin/ru/madbrains/mad_pay/MadPayPlugin.kt

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import androidx.annotation.NonNull
77
import androidx.annotation.Nullable
88
import com.google.android.gms.common.api.ApiException
99
import com.google.android.gms.wallet.*
10+
import com.google.protobuf.ByteString
1011
import io.flutter.embedding.engine.plugins.FlutterPlugin
1112
import io.flutter.embedding.engine.plugins.activity.ActivityAware
1213
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
@@ -44,10 +45,10 @@ class MadPayPlugin : FlutterPlugin, MethodCallHandler, PluginRegistry.ActivityRe
4445
activeResult.success(res.toByteArray())
4546
}
4647

47-
private fun invokeSuccessResult(@Nullable data: Map<String, String>?) {
48+
private fun invokeSuccessResult(@Nullable data: ByteArray?) {
4849
val res = MadPay.Response.newBuilder().setSuccess(true)
4950
if (data != null)
50-
res.putAllData(data)
51+
res.data = ByteString.copyFrom(data)
5152

5253
activeResult.success(res.build().toByteArray())
5354
}
@@ -62,14 +63,14 @@ class MadPayPlugin : FlutterPlugin, MethodCallHandler, PluginRegistry.ActivityRe
6263
activeResult.success(res.build().toByteArray())
6364
}
6465

65-
private fun invokeErrorResult(@Nullable errorCode: String?, @Nullable message: String?, @Nullable data: Map<String, String>?) {
66+
private fun invokeErrorResult(@Nullable errorCode: String?, @Nullable message: String?, @Nullable data: ByteArray?) {
6667
val res = MadPay.Response.newBuilder().setSuccess(false)
6768
if (errorCode != null)
6869
res.errorCode = errorCode
6970
if (message != null)
7071
res.message = message
7172
if (data != null)
72-
res.putAllData(data)
73+
res.data = ByteString.copyFrom(data)
7374

7475
activeResult.success(res.build().toByteArray())
7576
}
@@ -181,15 +182,7 @@ class MadPayPlugin : FlutterPlugin, MethodCallHandler, PluginRegistry.ActivityRe
181182
Activity.RESULT_OK -> {
182183
data?.let {
183184
PaymentData.getFromIntent(it)?.let { paymentData ->
184-
val paymentDataJSONObject = JSONObject(paymentData.toJson())
185-
(paymentDataJSONObject["paymentMethodData"] as? JSONObject)?.let { paymentMethodData ->
186-
(paymentMethodData["tokenizationData"] as? JSONObject)?.let { tokenizationData ->
187-
(tokenizationData["token"] as? String)?.let { token ->
188-
val response: Map<String, String> = mapOf(TOKEN to token)
189-
invokeSuccessResult(response)
190-
}
191-
}
192-
}
185+
invokeSuccessResult(paymentData.toJson().toByteArray())
193186
}
194187
}
195188
}
@@ -199,7 +192,7 @@ class MadPayPlugin : FlutterPlugin, MethodCallHandler, PluginRegistry.ActivityRe
199192
val errorData: Map<String, String> = mapOf("statusCode" to status?.statusCode.toString(),
200193
"statusMessage" to status?.statusMessage.toString())
201194

202-
invokeErrorResult(INVALID_PAYMENT_CODE, "Google Pay returned payment error", errorData)
195+
invokeErrorResult(INVALID_PAYMENT_CODE, "Google Pay returned payment error", errorData.toString().toByteArray())
203196
}
204197
}
205198
}

example/lib/main.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ class _MyAppState extends State<MyApp> {
6767
TextButton(
6868
onPressed: () async {
6969
try {
70-
final Map<String, String>? req =
71-
await pay.processingPayment(
70+
final PaymentResponse? req = await pay.processingPayment(
7271
google: GoogleParameters(
7372
gatewayName: 'example',
7473
gatewayMerchantId: 'example_id',
@@ -108,7 +107,7 @@ class _MyAppState extends State<MyApp> {
108107
],
109108
);
110109
setState(() {
111-
result = 'Try to pay:\n$req';
110+
result = 'Try to pay:\n${req?.token}';
112111
});
113112
} catch (e) {
114113
setState(() {

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ packages:
7373
path: ".."
7474
relative: true
7575
source: path
76-
version: "2.0.4"
76+
version: "2.1.0"
7777
matcher:
7878
dependency: transitive
7979
description:

ios/Classes/Constants.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
struct Constants {
22
static let channel: String = "mad_pay"
33

4-
static let token: String = "token"
5-
64
static let payment: String = "payment"
75
static let checkPayments: String = "checkPayments"
86
static let checkActiveCard: String = "checkActiveCard"

ios/Classes/PaymentHelpers.swift

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,221 @@ class PaymentNetworkHelper {
205205
return address
206206
}
207207
}
208+
209+
extension PKPayment: Encodable {
210+
public func encode(to encoder: Encoder) throws {
211+
var container = encoder.container(keyedBy: CodingKeys.self)
212+
try container.encode(self.token, forKey: .token)
213+
try container.encode(self.billingContact, forKey: .billingContact)
214+
try container.encode(self.shippingContact, forKey: .shippingContact)
215+
try container.encode(self.shippingMethod, forKey: .shippingMethod)
216+
}
217+
218+
enum CodingKeys: String, CodingKey {
219+
case token
220+
case billingContact
221+
case shippingContact
222+
case shippingAddress
223+
case billingAddress
224+
case shippingMethod
225+
}
226+
}
227+
228+
extension PKShippingMethod: Encodable {
229+
public func encode(to encoder: Encoder) throws {
230+
var container = encoder.container(keyedBy: CodingKeys.self)
231+
try container.encode(self.identifier, forKey: .identifier)
232+
try container.encode(self.detail, forKey: .detail)
233+
try container.encode(self.label, forKey: .label)
234+
}
235+
236+
enum CodingKeys: String, CodingKey {
237+
case identifier
238+
case detail
239+
case label
240+
}
241+
}
242+
243+
extension PKPaymentToken: Encodable {
244+
public func encode(to encoder: Encoder) throws {
245+
var container = encoder.container(keyedBy: CodingKeys.self)
246+
try container.encode(self.paymentMethod, forKey: .paymentMethod)
247+
try container.encode(self.paymentData, forKey: .paymentData)
248+
try container.encode(self.transactionIdentifier, forKey: .transactionIdentifier)
249+
}
250+
251+
enum CodingKeys: String, CodingKey {
252+
case paymentNetwork
253+
case paymentMethod
254+
case paymentData
255+
case paymentInstrumentName
256+
case transactionIdentifier
257+
}
258+
}
259+
260+
extension PKPaymentMethod: Encodable {
261+
public func encode(to encoder: Encoder) throws {
262+
var container = encoder.container(keyedBy: CodingKeys.self)
263+
if #available(iOS 13.0, *) {
264+
try container.encode(self.billingAddress, forKey: .billingAddress)
265+
}
266+
try container.encode(self.displayName, forKey: .displayName)
267+
try container.encode(self.network?.rawValue, forKey: .network)
268+
try container.encode(self.paymentPass, forKey: .paymentPass)
269+
if #available(iOS 13.4, *) {
270+
try container.encode(self.secureElementPass, forKey: .secureElementPass)
271+
}
272+
try container.encode(self.type.rawValue, forKey: .type)
273+
}
274+
275+
enum CodingKeys: String, CodingKey {
276+
case billingAddress
277+
case displayName
278+
case network
279+
case paymentPass
280+
case secureElementPass
281+
case type
282+
}
283+
}
284+
285+
286+
@available(iOS 13.4, *)
287+
extension PKSecureElementPass: Encodable {
288+
public func encode(to encoder: Encoder) throws {
289+
var container = encoder.container(keyedBy: CodingKeys.self)
290+
try container.encode(self.secureElementPass, forKey: .secureElementPass)
291+
try container.encode(self.paymentPass, forKey: .paymentPass)
292+
}
293+
294+
enum CodingKeys: String, CodingKey {
295+
case secureElementPass
296+
case paymentPass
297+
}
298+
}
299+
300+
extension PKContact: Encodable {
301+
public func encode(to encoder: Encoder) throws {
302+
var container = encoder.container(keyedBy: CodingKeys.self)
303+
try container.encode(self.name, forKey: .name)
304+
if #available(iOS 9.2, *) {
305+
try container.encode(self.supplementarySubLocality, forKey: .supplementarySubLocality)
306+
}
307+
try container.encode(self.postalAddress, forKey: .postalAddress)
308+
try container.encode(self.phoneNumber, forKey: .phoneNumber)
309+
try container.encode(self.emailAddress, forKey: .emailAddress)
310+
}
311+
312+
enum CodingKeys: String, CodingKey {
313+
case name
314+
case supplementarySubLocality
315+
case postalAddress
316+
case phoneNumber
317+
case emailAddress
318+
}
319+
}
320+
321+
extension CNPostalAddress: Encodable {
322+
public func encode(to encoder: Encoder) throws {
323+
var container = encoder.container(keyedBy: CodingKeys.self)
324+
if #available(iOS 10.3, *) {
325+
try container.encode(self.subLocality, forKey: .subLocality)
326+
try container.encode(self.subAdministrativeArea, forKey: .subAdministrativeArea)
327+
}
328+
try container.encode(self.street, forKey: .street)
329+
try container.encode(self.state, forKey: .state)
330+
try container.encode(self.postalCode, forKey: .postalCode)
331+
try container.encode(self.isoCountryCode, forKey: .isoCountryCode)
332+
try container.encode(self.country, forKey: .country)
333+
try container.encode(self.city, forKey: .city)
334+
}
335+
336+
enum CodingKeys: String, CodingKey {
337+
case subLocality
338+
case subAdministrativeArea
339+
case street
340+
case state
341+
case postalCode
342+
case isoCountryCode
343+
case country
344+
case city
345+
}
346+
}
347+
348+
extension CNPhoneNumber: Encodable {
349+
public func encode(to encoder: Encoder) throws {
350+
var container = encoder.container(keyedBy: CodingKeys.self)
351+
try container.encode(self.stringValue, forKey: .stringValue)
352+
}
353+
354+
enum CodingKeys: String, CodingKey {
355+
case stringValue
356+
}
357+
}
358+
359+
extension CNContact: Encodable {
360+
public func encode(to encoder: Encoder) throws {
361+
var container = encoder.container(keyedBy: CodingKeys.self)
362+
try container.encode(self.identifier, forKey: .identifier)
363+
try container.encode(self.contactType.rawValue, forKey: .contactType)
364+
try container.encode(self.namePrefix, forKey: .namePrefix)
365+
try container.encode(self.givenName, forKey: .givenName)
366+
try container.encode(self.middleName, forKey: .middleName)
367+
try container.encode(self.familyName, forKey: .familyName)
368+
try container.encode(self.previousFamilyName, forKey: .previousFamilyName)
369+
try container.encode(self.nameSuffix, forKey: .nameSuffix)
370+
try container.encode(self.nickname, forKey: .nickname)
371+
try container.encode(self.organizationName, forKey: .organizationName)
372+
try container.encode(self.departmentName, forKey: .departmentName)
373+
try container.encode(self.jobTitle, forKey: .jobTitle)
374+
try container.encode(self.phoneticGivenName, forKey: .phoneticGivenName)
375+
try container.encode(self.phoneticMiddleName, forKey: .phoneticMiddleName)
376+
try container.encode(self.phoneticFamilyName, forKey: .phoneticFamilyName)
377+
try container.encode(self.note, forKey: .note)
378+
try container.encode(self.imageData, forKey: .imageData)
379+
try container.encode(self.thumbnailImageData, forKey: .thumbnailImageData)
380+
try container.encode(self.imageDataAvailable, forKey: .imageDataAvailable)
381+
// try container.encode(self.phoneNumbers, forKey: .phoneNumbers)
382+
// try container.encode(self.emailAddresses, forKey: .emailAddresses)
383+
// try container.encode(self.postalAddresses, forKey: .postalAddresses)
384+
// try container.encode(self.urlAddresses, forKey: .urlAddresses)
385+
// try container.encode(self.contactRelations, forKey: .contactRelations)
386+
// try container.encode(self.socialProfiles, forKey: .socialProfiles)
387+
// try container.encode(self.instantMessageAddresses, forKey: .instantMessageAddresses)
388+
try container.encode(self.birthday, forKey: .birthday)
389+
try container.encode(self.nonGregorianBirthday, forKey: .nonGregorianBirthday)
390+
// try container.encode(self.dates, forKey: .dates)
391+
}
392+
393+
enum CodingKeys: String, CodingKey {
394+
case identifier
395+
case contactType
396+
case namePrefix
397+
case givenName
398+
case middleName
399+
case familyName
400+
case previousFamilyName
401+
case nameSuffix
402+
case nickname
403+
case organizationName
404+
case departmentName
405+
case jobTitle
406+
case phoneticGivenName
407+
case phoneticMiddleName
408+
case phoneticFamilyName
409+
case phoneticOrganizationName
410+
case note
411+
case imageData
412+
case thumbnailImageData
413+
case imageDataAvailable
414+
case phoneNumbers
415+
case emailAddresses
416+
case postalAddresses
417+
case urlAddresses
418+
case contactRelations
419+
case socialProfiles
420+
case instantMessageAddresses
421+
case birthday
422+
case nonGregorianBirthday
423+
case dates
424+
}
425+
}

ios/Classes/SwiftMadPayPlugin.swift

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class SwiftMadPayPlugin: NSObject, FlutterPlugin {
1313
registrar.addMethodCallDelegate(instance, channel: channel)
1414
}
1515

16-
func invokeSuccessResult(success: Bool = true, data: Dictionary<String, String>? = nil) {
16+
func invokeSuccessResult(success: Bool = true, data: Data? = nil) {
1717
try! activeResult!(Response.with { (res) in
1818
res.success = success
1919
if let data = data {
@@ -57,7 +57,7 @@ public class SwiftMadPayPlugin: NSObject, FlutterPlugin {
5757
}
5858

5959
func switchEnvironment(arguments: EnvironmentRequest) {
60-
invokeErrorResult(success: true, errorCode: Constants.notImplementedCode, message: "Method not implemented")
60+
invokeErrorResult(success: true, errorCode: Constants.notImplementedCode, message: "\"environments\" is not supported by Apple Pay")
6161
}
6262

6363
func checkPayments() {
@@ -119,11 +119,10 @@ public class SwiftMadPayPlugin: NSObject, FlutterPlugin {
119119

120120
private func paymentResult(pkPayment: PKPayment?) {
121121
if let payment = pkPayment {
122-
let token = String(data: payment.token.paymentData, encoding: .utf8)
123-
invokeSuccessResult(data: [
124-
"transactionId": payment.token.transactionIdentifier,
125-
Constants.token: token!,
126-
])
122+
let jsonEncoder = JSONEncoder()
123+
let jsonData = try! jsonEncoder.encode(payment)
124+
let paymentResult = String(data: jsonData, encoding: .utf8)
125+
invokeSuccessResult(data: paymentResult?.data(using: .utf8))
127126
} else {
128127
invokeErrorResult(errorCode: Constants.cancelledCode, message: "User cancelled the payment")
129128
}

0 commit comments

Comments
 (0)