-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
3588 lines (3405 loc) · 229 KB
/
Copy pathindex.html
File metadata and controls
3588 lines (3405 loc) · 229 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta
name="description"
content="Documentation for the Odero API"
>
<title>API Reference</title>
<style media="screen">
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight .gh {
color: #999999;
}
.highlight .sr {
color: #f6aa11;
}
.highlight .go {
color: #888888;
}
.highlight .gp {
color: #555555;
}
.highlight .gs {
}
.highlight .gu {
color: #aaaaaa;
}
.highlight .nb {
color: #f6aa11;
}
.highlight .cm {
color: #75715e;
}
.highlight .cp {
color: #75715e;
}
.highlight .c1 {
color: #75715e;
}
.highlight .cs {
color: #75715e;
}
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cpf {
color: #75715e;
}
.highlight .err {
color: #960050;
}
.highlight .gr {
color: #960050;
}
.highlight .gt {
color: #960050;
}
.highlight .gd {
color: #49483e;
}
.highlight .gi {
color: #49483e;
}
.highlight .ge {
color: #49483e;
}
.highlight .kc {
color: #66d9ef;
}
.highlight .kd {
color: #66d9ef;
}
.highlight .kr {
color: #66d9ef;
}
.highlight .no {
color: #66d9ef;
}
.highlight .kt {
color: #66d9ef;
}
.highlight .mf {
color: #ae81ff;
}
.highlight .mh {
color: #ae81ff;
}
.highlight .il {
color: #ae81ff;
}
.highlight .mi {
color: #ae81ff;
}
.highlight .mo {
color: #ae81ff;
}
.highlight .m, .highlight .mb, .highlight .mx {
color: #ae81ff;
}
.highlight .sc {
color: #ae81ff;
}
.highlight .se {
color: #ae81ff;
}
.highlight .ss {
color: #ae81ff;
}
.highlight .sd {
color: #e6db74;
}
.highlight .s2 {
color: #e6db74;
}
.highlight .sb {
color: #e6db74;
}
.highlight .sh {
color: #e6db74;
}
.highlight .si {
color: #e6db74;
}
.highlight .sx {
color: #e6db74;
}
.highlight .s1 {
color: #e6db74;
}
.highlight .s, .highlight .sa, .highlight .dl {
color: #e6db74;
}
.highlight .na {
color: #a6e22e;
}
.highlight .nc {
color: #a6e22e;
}
.highlight .nd {
color: #a6e22e;
}
.highlight .ne {
color: #a6e22e;
}
.highlight .nf, .highlight .fm {
color: #a6e22e;
}
.highlight .vc {
color: #ffffff;
}
.highlight .nn {
color: #ffffff;
}
.highlight .ni {
color: #ffffff;
}
.highlight .bp {
color: #ffffff;
}
.highlight .vg {
color: #ffffff;
}
.highlight .vi {
color: #ffffff;
}
.highlight .nv, .highlight .vm {
color: #ffffff;
}
.highlight .w {
color: #ffffff;
}
.highlight {
color: #ffffff;
}
.highlight .n, .highlight .py, .highlight .nx {
color: #ffffff;
}
.highlight .nl {
color: #f92672;
}
.highlight .ow {
color: #f92672;
}
.highlight .nt {
color: #f92672;
}
.highlight .k, .highlight .kv {
color: #f92672;
}
.highlight .kn {
color: #f92672;
}
.highlight .kp {
color: #f92672;
}
.highlight .o {
color: #f92672;
}
</style>
<style media="print">
* {
-webkit-transition:none!important;
transition:none!important;
}
.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight, .highlight .w {
color: #586e75;
}
.highlight .err {
color: #002b36;
background-color: #dc322f;
}
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cm, .highlight .cpf, .highlight .c1, .highlight .cs {
color: #657b83;
}
.highlight .cp {
color: #b58900;
}
.highlight .nt {
color: #b58900;
}
.highlight .o, .highlight .ow {
color: #93a1a1;
}
.highlight .p, .highlight .pi {
color: #93a1a1;
}
.highlight .gi {
color: #859900;
}
.highlight .gd {
color: #dc322f;
}
.highlight .gh {
color: #268bd2;
background-color: #002b36;
font-weight: bold;
}
.highlight .k, .highlight .kn, .highlight .kp, .highlight .kr, .highlight .kv {
color: #6c71c4;
}
.highlight .kc {
color: #cb4b16;
}
.highlight .kt {
color: #cb4b16;
}
.highlight .kd {
color: #cb4b16;
}
.highlight .s, .highlight .sb, .highlight .sc, .highlight .dl, .highlight .sd, .highlight .s2, .highlight .sh, .highlight .sx, .highlight .s1 {
color: #859900;
}
.highlight .sa {
color: #6c71c4;
}
.highlight .sr {
color: #2aa198;
}
.highlight .si {
color: #d33682;
}
.highlight .se {
color: #d33682;
}
.highlight .nn {
color: #b58900;
}
.highlight .nc {
color: #b58900;
}
.highlight .no {
color: #b58900;
}
.highlight .na {
color: #268bd2;
}
.highlight .m, .highlight .mb, .highlight .mf, .highlight .mh, .highlight .mi, .highlight .il, .highlight .mo, .highlight .mx {
color: #859900;
}
.highlight .ss {
color: #859900;
}
</style>
<link href="stylesheets/screen-c9d8fa83.css" rel="stylesheet" media="screen" />
<link href="stylesheets/print-953e3353.css" rel="stylesheet" media="print" />
<script src="javascripts/all-b12a2749.js"></script>
<script>
$(function() { setupCodeCopy(); });
</script>
</head>
<body class="index" data-languages="["php","json"]">
<a href="#" id="nav-button">
<span>
NAV
<img src="images/navbar-cad8cdcb.png" alt="" />
</span>
</a>
<div class="toc-wrapper">
<img src="images/logo-cc102dc1.png" class="logo" alt="" />
<div class="lang-selector">
<a href="#" data-language-name="php">php</a>
<a href="#" data-language-name="json">json</a>
</div>
<div class="search">
<input type="text" class="search" id="input-search" placeholder="Search">
</div>
<ul class="search-results"></ul>
<ul id="toc" class="toc-list-h1">
<li>
<a href="#introduction" class="toc-h1 toc-link" data-title="Introduction">Introduction</a>
<ul class="toc-list-h2">
<li>
<a href="#installation" class="toc-h2 toc-link" data-title="Installation">Installation</a>
</li>
<li>
<a href="#authentication" class="toc-h2 toc-link" data-title="Authentication">Authentication</a>
</li>
</ul>
</li>
<li>
<a href="#in-app-payment" class="toc-h1 toc-link" data-title="In-App Payment">In-App Payment</a>
<ul class="toc-list-h2">
<li>
<a href="#in-app-introduction" class="toc-h2 toc-link" data-title="In-App - Introduction">Introduction</a>
</li>
<li>
<a href="#in-app-how-it-works" class="toc-h2 toc-link" data-title="In-App - How it works">How it works</a>
</li>
<li>
<a href="#in-app-requirements" class="toc-h2 toc-link" data-title="In-App - Requirements">Requirements</a>
</li>
<li>
<a href="#in-app-merchant-setup" class="toc-h2 toc-link" data-title="In-App - Merchant setup and sessions">Merchant setup & sessions</a>
</li>
<li>
<a href="#in-app-payment-types" class="toc-h2 toc-link" data-title="In-App - Payment types">Payment types</a>
</li>
<li>
<a href="#in-app-ios" class="toc-h2 toc-link" data-title="In-App - iOS">iOS</a>
</li>
<li>
<a href="#in-app-android" class="toc-h2 toc-link" data-title="In-App - Android">Android</a>
</li>
<li>
<a href="#in-app-react-native" class="toc-h2 toc-link" data-title="In-App - React Native">React Native</a>
</li>
<li>
<a href="#in-app-customization" class="toc-h2 toc-link" data-title="In-App - Customizing the sheet">Customizing the sheet</a>
</li>
<li>
<a href="#in-app-sample-apps" class="toc-h2 toc-link" data-title="In-App - Sample apps">Sample apps</a>
</li>
</ul>
</li>
<li>
<a href="#card-operations" class="toc-h1 toc-link" data-title="Card Operations">Card Operations</a>
<ul class="toc-list-h2">
<li>
<a href="#store-card" class="toc-h2 toc-link" data-title="Store Card">Store Card</a>
</li>
<li>
<a href="#delete-card" class="toc-h2 toc-link" data-title="Delete Card">Delete Card</a>
</li>
</ul>
</li>
<li>
<a href="#payments" class="toc-h1 toc-link" data-title="Payments">Payments</a>
<ul class="toc-list-h2">
<li>
<a href="#create-payment-request" class="toc-h2 toc-link" data-title="Create Payment Request">Create Payment Request</a>
</li>
<li>
<a href="#create-payment-link" class="toc-h2 toc-link" data-title="Create Payment Link">Create Payment Link</a>
</li>
<li>
<a href="#get-payment" class="toc-h2 toc-link" data-title="Get Payment">Get Payment</a>
</li>
<li>
<a href="#marketplace" class="toc-h2 toc-link" data-title="Marketplace">Marketplace</a>
</li>
<li>
<a href="#pay-with-saved-card" class="toc-h2 toc-link" data-title="Pay With Saved Card">Pay With Saved Card</a>
</li>
<li>
<a href="#deposit-the-authorized-transaction" class="toc-h2 toc-link" data-title="Deposit the Authorized Transaction">Deposit the Authorized Transaction</a>
</li>
<li>
<a href="#reverse-the-authorized-transaction" class="toc-h2 toc-link" data-title="Reverse the Authorized Transaction">Reverse the Authorized Transaction</a>
</li>
<li>
<a href="#refund-deposited-transaction" class="toc-h2 toc-link" data-title="Refund Deposited Transaction">Refund Deposited Transaction</a>
</li>
<li>
<a href="#refund-deposited-transaction-2" class="toc-h2 toc-link" data-title="Refund Deposited Transaction">Refund Deposited Transaction</a>
</li>
</ul>
</li>
<li>
<a href="#subscriptions" class="toc-h1 toc-link" data-title="Subscriptions">Subscriptions</a>
<ul class="toc-list-h2">
<li>
<a href="#create-subscription" class="toc-h2 toc-link" data-title="Create Subscription">Create Subscription</a>
</li>
<li>
<a href="#retry" class="toc-h2 toc-link" data-title="Retry">Retry</a>
</li>
<li>
<a href="#cancel" class="toc-h2 toc-link" data-title="Cancel">Cancel</a>
</li>
</ul>
</li>
<li>
<a href="#webhooks" class="toc-h1 toc-link" data-title="Webhooks">Webhooks</a>
<ul class="toc-list-h2">
<li>
<a href="#payment" class="toc-h2 toc-link" data-title="Payment">Payment</a>
</li>
<li>
<a href="#deposit" class="toc-h2 toc-link" data-title="Deposit">Deposit</a>
</li>
<li>
<a href="#reverse" class="toc-h2 toc-link" data-title="Reverse">Reverse</a>
</li>
<li>
<a href="#refund" class="toc-h2 toc-link" data-title="Refund">Refund</a>
</li>
<li>
<a href="#stored-card" class="toc-h2 toc-link" data-title="Stored Card">Stored Card</a>
</li>
<li>
<a href="#remove-card" class="toc-h2 toc-link" data-title="Remove Card">Remove Card</a>
</li>
<li>
<a href="#status-codes" class="toc-h2 toc-link" data-title="Status Codes">Status Codes</a>
</li>
</ul>
</li>
<li>
<a href="#open-source" class="toc-h1 toc-link" data-title="Open Source">Open Source</a>
<ul class="toc-list-h2">
<li>
<a href="#opencart" class="toc-h2 toc-link" data-title="Opencart">Opencart</a>
</li>
<li>
<a href="#woocommerce" class="toc-h2 toc-link" data-title="Woocommerce">Woocommerce</a>
</li>
</ul>
</li>
<li>
<a href="#test-cards" class="toc-h1 toc-link" data-title="Test Cards">Test Cards</a>
</li>
<li>
<a href="#errors" class="toc-h1 toc-link" data-title="Errors">Errors</a>
</li>
</ul>
<ul class="toc-footer">
<li><a href='https://odero.ro'>Return to Odero Homepage </a></li>
</ul>
</div>
<div class="page-wrapper">
<div class="dark-box"></div>
<div class="content">
<h1 id='introduction'>Introduction</h1>
<p>Welcome to the OderoPay API! You can use our API to access Odero API endpoints, which can get information on various payments, cards, recurrings, deposits, refunds in our database.</p>
<p>We have language bindings in Shell, Php, Python, and Nodejs! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.</p>
<h2 id='installation'>Installation</h2>
<p>You can access our SDK's directly on our <a href="https://github.com/oderopay">Github</a> Page.</p>
<h3 id='php'>PHP</h3>
<p><a href="https://github.com/oderopay/odero-php">Odero PHP Sdk</a></p>
<p><code>composer require oderopay/odero-php</code></p>
<p>Minimum Requirements;</p>
<ul>
<li>PHP 7.2 or later</li>
<li>curl</li>
<li>json</li>
<li>mbstring</li>
</ul>
<h2 id='authentication'>Authentication</h2>
<blockquote>
<p>To authorize, use this code:</p>
</blockquote>
<div class="highlight"><pre class="highlight php tab-php"><code><span class="c1">//Authentication is already handled by SDK</span>
<span class="nv">$config</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nf">Oderopay\OderoConfig</span><span class="p">(</span><span class="s1">'My Store Name'</span><span class="p">,</span> <span class="s1">'{merchant-id}'</span><span class="p">,</span> <span class="s1">'{merchant-token}'</span><span class="p">,</span> <span class="err">\</span><span class="nc">Oderopay\OderoConfig</span><span class="o">::</span><span class="no">ENV_STG</span><span class="p">);</span>
<span class="c1">//Just initialize the Odero Client with given config.</span>
<span class="nv">$oderopay</span> <span class="o">=</span> <span class="k">new</span> <span class="err">\</span><span class="nf">Oderopay\OderoClient</span><span class="p">(</span><span class="nv">$config</span><span class="p">);</span>
</code></pre></div>
<p>To be authenticated, you need to send <code>X-MERCHANT-SIGNATURE</code> value in header.</p>
<p>The header X-MERCHANT-SIGNATURE is generated by each merchant when a new request is initialized to API Endpoints.</p>
<p>Items used in header generation:</p>
<ul>
<li>Merchant ID;</li>
<li>Payload (encoded as json);</li>
<li>Merchant API Token.</li>
</ul>
<p>Used Algorithm: sha256</p>
<p>How is the header generated?</p>
<aside>
MERCHANT-ID + | + sha256(MERCHANT-ID + PAYLOADED_ENCODED_AS_JSON + MERCHANT-API-TOKEN)
</aside>
<!-- In-App Payment -->
<h1 id='in-app-payment'>In-App Payment</h1>
<h2 id='in-app-introduction'>Introduction</h2>
<div class="content">
<p>
The Odero In-App Payment SDK lets you take card and wallet payments
<strong>inside your own mobile app</strong>, without sending the customer to a
browser and without your app ever touching raw card data. You drop in a
ready-made, fully themeable payment sheet; the customer enters their card (or
pays with Apple Pay / Google Pay); the SDK runs 3-D Secure and
settles the charge with Odero; and you get the result back.
</p>
<p>
It ships as three native SDKs that expose the same flow and the same payment
sheet:
</p>
<ul>
<li><strong>iOS</strong>: <code>OderoPaySDKIOS</code>, distributed as a CocoaPods xcframework.</li>
<li><strong>Android</strong>: <code>oderopaysdkandroid</code>, distributed as a Maven (AAR) library.</li>
<li><strong>React Native</strong>: <code>react-native-oderopay</code>, a pure-RN package that wraps the same flow.</li>
</ul>
<p><strong>Capabilities:</strong></p>
<ul>
<li>Card payments with built-in validation (Luhn, brand detection, expiry, CVC).</li>
<li>Stored / saved cards (one-tap, token-based).</li>
<li>Apple Pay on iOS and Google Pay on Android.</li>
<li>3-D Secure handled automatically in an in-sheet web view.</li>
<li>A drop-in payment sheet you can theme down to colours, fonts, labels and icons.</li>
<li>The customer never types card data into <em>your</em> code, which keeps your PCI scope minimal.</li>
</ul>
<p>
The card data is captured by Odero's UI and the actual charge is created
server-to-server, so your application only ever handles an opaque
<code style="white-space: nowrap">sessionId</code> and a result status.
</p>
<p><strong>The two pieces you build:</strong></p>
<ol>
<li>
<p>A small piece of <strong>backend</strong> code that creates a payment
<em>session</em> with your secret merchant credentials and returns a
<code style="white-space: nowrap">sessionId</code> to the app. See
<a href="#in-app-merchant-setup">Merchant setup & sessions</a>.</p>
</li>
<li>
<p>The <strong>app</strong> integration: hand that
<code style="white-space: nowrap">sessionId</code> to the SDK and show
the payment sheet. See
<a href="#in-app-ios">iOS</a>, <a href="#in-app-android">Android</a> or
<a href="#in-app-react-native">React Native</a>.</p>
</li>
</ol>
<p>
Read <a href="#in-app-how-it-works">How it works</a> next for the end-to-end
flow, then jump to your platform.
</p>
</div>
<h2 id='in-app-how-it-works'>How it works</h2>
<div class="content">
<svg viewBox="0 0 760 132" width="100%" style="max-width:760px;height:auto;margin:10px 0;font-family:inherit" role="img" aria-label="In-App payment flow: create session on your backend, show the sheet with the session id, the customer pays, you receive the result">
<defs>
<marker id="ia-arrow" markerWidth="9" markerHeight="9" refX="6" refY="3" orient="auto">
<path d="M0,0 L6,3 L0,6 Z" fill="#9aa0a6"></path>
</marker>
</defs>
<g>
<rect x="8" y="34" width="168" height="64" rx="8" fill="#eef2f6" stroke="#c9d2db"></rect>
<text x="92" y="62" text-anchor="middle" font-size="14" fill="#1f2d3d">1. Create session</text>
<text x="92" y="80" text-anchor="middle" font-size="11" fill="#5b6b7b">your backend → Odero</text>
</g>
<line x1="176" y1="66" x2="194" y2="66" stroke="#9aa0a6" stroke-width="2" marker-end="url(#ia-arrow)"></line>
<g>
<rect x="198" y="34" width="168" height="64" rx="8" fill="#eef2f6" stroke="#c9d2db"></rect>
<text x="282" y="62" text-anchor="middle" font-size="14" fill="#1f2d3d">2. Show sheet</text>
<text x="282" y="80" text-anchor="middle" font-size="11" fill="#5b6b7b">app passes sessionId</text>
</g>
<line x1="366" y1="66" x2="384" y2="66" stroke="#9aa0a6" stroke-width="2" marker-end="url(#ia-arrow)"></line>
<g>
<rect x="388" y="34" width="168" height="64" rx="8" fill="#eef2f6" stroke="#c9d2db"></rect>
<text x="472" y="62" text-anchor="middle" font-size="14" fill="#1f2d3d">3. Customer pays</text>
<text x="472" y="80" text-anchor="middle" font-size="11" fill="#5b6b7b">card / wallet · 3-D Secure</text>
</g>
<line x1="556" y1="66" x2="574" y2="66" stroke="#9aa0a6" stroke-width="2" marker-end="url(#ia-arrow)"></line>
<g>
<rect x="578" y="34" width="168" height="64" rx="8" fill="#eef2f6" stroke="#c9d2db"></rect>
<text x="662" y="62" text-anchor="middle" font-size="14" fill="#1f2d3d">4. Receive result</text>
<text x="662" y="80" text-anchor="middle" font-size="11" fill="#5b6b7b">success / failure</text>
</g>
</svg>
<p>
A payment has two sides: a one-time-per-checkout <strong>session</strong>
created by your <strong>backend</strong>, and the <strong>app</strong> that
shows the sheet for that session. The split exists for security: your secret
merchant credentials live only on your server, and the app only ever sees an
opaque <code style="white-space: nowrap">sessionId</code>.
</p>
<h3>1. Your backend creates a session</h3>
<p>
For each checkout, your server calls Odero with your merchant credentials,
the amount, currency and the basket, and gets back a
<code style="white-space: nowrap">sessionId</code>. The session also records
which payment methods are allowed (card, Apple Pay, Google Pay). This
is a two-step signed call. See
<a href="#in-app-merchant-setup">Merchant setup & sessions</a>.
</p>
<h3>2. The app shows the payment sheet</h3>
<p>
Your app receives the <code style="white-space: nowrap">sessionId</code> from
your backend and hands it to the SDK
(<code style="white-space: nowrap">showPaymentSheet</code>). The SDK fetches the
session, reads the amount, currency and the allowed methods, and renders the
sheet: the card form, saved cards, and the Apple Pay / Google Pay button
when the session allows it.
</p>
<h3>3. The customer pays</h3>
<p>The SDK runs the whole payment for you:</p>
<ol>
<li>The customer picks a method and confirms.</li>
<li>The SDK creates the payment with Odero.</li>
<li>If the bank requires <strong>3-D Secure</strong>, the SDK opens the bank's challenge in an in-sheet web view and closes it automatically when done. No code from you.</li>
<li>The SDK polls the payment status until it reaches a terminal state.</li>
</ol>
<h3>4. You receive the result</h3>
<p>
The SDK shows a success or failure page in the sheet, and reports the outcome
to your code as a status: <code style="white-space: nowrap">processing</code> →
<code style="white-space: nowrap">success</code> or
<code style="white-space: nowrap">failure</code>. On success you get a
reference number; on failure you get a message. How you receive it differs per
platform (a notification on iOS, a callback on Android, a hook/event on React
Native). See your platform page.
</p>
<aside class="notice">
<strong>Amounts & currency.</strong> You set the amount when you create the
session (major units, e.g. <code style="white-space: nowrap">50.0</code> RON).
The SDK never takes an amount from the app; it reads the amount from the session, so
the displayed total can't be tampered with on the device. Currency is RON and
country is RO.
</aside>
<p>
The same four steps apply to every platform; only the API names change. Next:
<a href="#in-app-requirements">Requirements</a>,
<a href="#in-app-merchant-setup">Merchant setup & sessions</a>, and
<a href="#in-app-payment-types">Payment types</a>.
</p>
</div>
<h2 id='in-app-requirements'>Requirements</h2>
<div class="content">
<p>
Minimum platform and toolchain versions for each SDK. All three SDKs are
released under the <strong>same version number</strong>; replace
<code style="white-space: nowrap">1.0.0</code> in the snippets throughout these
docs with the version Odero gave you.
</p>
<h3>iOS</h3>
<table>
<thead><tr><th>Requirement</th><th>Value</th></tr></thead>
<tbody>
<tr><td>Deployment target</td><td>iOS 15.0+</td></tr>
<tr><td>Swift</td><td>5.0</td></tr>
<tr><td>Distribution</td><td>CocoaPods (binary xcframework)</td></tr>
<tr><td>Links</td><td><code style="white-space: nowrap">PassKit</code> (Apple Pay), C++ standard library (handled by the pod)</td></tr>
<tr><td>Apple Pay testing</td><td>A real device (the simulator cannot authorize)</td></tr>
</tbody>
</table>
<h3>Android</h3>
<table>
<thead><tr><th>Requirement</th><th>Value</th></tr></thead>
<tbody>
<tr><td><code style="white-space: nowrap">minSdk</code></td><td>23</td></tr>
<tr><td><code style="white-space: nowrap">compileSdk</code> / <code style="white-space: nowrap">targetSdk</code></td><td>35</td></tr>
<tr><td>JDK</td><td>17</td></tr>
<tr><td>Android Gradle Plugin</td><td>8.7.3+</td></tr>
<tr><td>Kotlin</td><td>2.1.20 (don't force a newer stdlib)</td></tr>
<tr><td>UI</td><td>Jetpack Compose (pulled in transitively; you don't need Compose yourself)</td></tr>
<tr><td>Host Activity</td><td>Must be a <code style="white-space: nowrap">ComponentActivity</code> (e.g. <code style="white-space: nowrap">AppCompatActivity</code>), required for Google Pay</td></tr>
<tr><td>Google Pay</td><td><code style="white-space: nowrap">com.google.android.gms:play-services-wallet:20.0.0</code></td></tr>
</tbody>
</table>
<h3>React Native</h3>
<table>
<thead><tr><th>Requirement</th><th>Value</th></tr></thead>
<tbody>
<tr><td>React Native</td><td>Any modern RN (built and tested on 0.81)</td></tr>
<tr><td>React</td><td>Any (tested on 19.x)</td></tr>
<tr><td>Peer dependency</td><td><code style="white-space: nowrap">react-native-webview >= 13.0.0</code> (required, for 3-D Secure)</td></tr>
<tr><td>Node</td><td>>= 20</td></tr>
<tr><td>iOS (native side)</td><td>iOS 12.0+ pod, <code style="white-space: nowrap">PassKit</code>; build on a real device for Apple Pay</td></tr>
<tr><td>Android (native side)</td><td><code style="white-space: nowrap">minSdk</code> 24, JDK 17, <code style="white-space: nowrap">play-services-wallet</code></td></tr>
</tbody>
</table>
<p>
The card-only flow on React Native is pure JavaScript plus
<code style="white-space: nowrap">react-native-webview</code>. Apple Pay /
Google Pay add an optional native wallet module. See
<a href="#in-app-react-native">React Native</a>.
</p>
</div>
<h2 id='in-app-merchant-setup'>Merchant setup & sessions</h2>
<div class="content">
<p>
Before you write any app code, a few things have to be registered in the Token
(Odero) ecosystem and kept on your <strong>backend</strong>. This section covers
what to obtain, and how your server turns it into a
<code style="white-space: nowrap">sessionId</code> for the app.
</p>
<h3>What you register with Odero</h3>
<table>
<thead><tr><th>Item</th><th>What it is</th><th>Where it lives</th></tr></thead>
<tbody>
<tr>
<td><strong>Merchant ID</strong></td>
<td>Your Odero merchant account id (a UUID). Identifies you and signs every session. Also used as the Google Pay <code style="white-space: nowrap">gatewayMerchantId</code>.</td>
<td>Your backend (not secret, but kept server-side)</td>
</tr>
<tr>
<td><strong>Merchant API token</strong></td>
<td>The secret token that authorizes session creation.</td>
<td>Your backend <strong>only</strong>, never in the app</td>
</tr>
<tr>
<td><strong>Apple Pay merchant identifier</strong></td>
<td>An Apple-issued id such as <code style="white-space: nowrap">merchant.com.yourapp</code>, plus a Payment Processing certificate. <strong>Must be uploaded to the Token platform</strong> so Odero can decrypt the Apple Pay token.</td>
<td>Apple Developer portal + uploaded to Odero; the id also goes in your app entitlement</td>
</tr>
<tr>
<td><strong>Google Pay merchant id</strong></td>
<td>From the Google Pay & Wallet Console (production only). The tokenization gateway is fixed to <code style="white-space: nowrap">oderopay</code>; the <code style="white-space: nowrap">gatewayMerchantId</code> sent to Google is your Odero merchant id.</td>
<td>Google console; nothing extra to register with Odero beyond your merchant account</td>
</tr>
</tbody>
</table>
<aside class="warning">
<strong>Keep secrets server-side.</strong> The merchant ID and merchant API
token create money-moving sessions. They must live only on your backend. Never
embed them in an iOS, Android or React Native build, and never expose them to a
browser. The app only ever receives a <code style="white-space: nowrap">sessionId</code>.
</aside>
<h3>The two "merchant id" values</h3>
<ul>
<li><strong>Odero merchant ID</strong> (a UUID). Used to sign sessions, and as the Google Pay <code style="white-space: nowrap">gatewayMerchantId</code>.</li>
<li><strong>Apple Pay merchant identifier</strong> (<code style="white-space: nowrap">merchant.com.yourapp</code>). A separate, Apple-issued id you pass to the SDK as <code style="white-space: nowrap">applePayMerchantId</code> and register in your app's Apple Pay entitlement.</li>
</ul>
<h3>Environments</h3>
<p>There are two environments, selected per platform (see each SDK page):</p>
<table>
<thead><tr><th>Environment</th><th>API host</th></tr></thead>
<tbody>
<tr><td>DEV</td><td><code style="white-space: nowrap">https://api-dev.pay.odero.ro/</code></td></tr>
<tr><td>PROD</td><td><code style="white-space: nowrap">https://pay.odero.ro/</code></td></tr>
</tbody>
</table>
<p>
For Google Pay, keep the wallet environment in sync with the API
environment: DEV uses Google Pay <em>TEST</em>, PROD uses
<em>PRODUCTION</em>.
</p>
<h3>Creating a payment session (on your backend)</h3>
<p>
For each checkout, your server makes a <strong>two-step signed call</strong>:
first it gets a one-time signature for the payload, then it creates the session
with that signature. The response is the
<code style="white-space: nowrap">sessionId</code> you pass to the app.
</p>
<blockquote><p>Backend: create a session (Node example, runs on your server)</p></blockquote>
<div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="kd">const</span><span class="w"> </span><span class="nx">BASE</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://api-dev.pay.odero.ro/'</span><span class="p">;</span><span class="w"> </span><span class="c1">// PROD: https://pay.odero.ro/</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">merchantId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">ODERO_MERCHANT_ID</span><span class="p">;</span><span class="w"> </span><span class="c1">// server-side secret</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">merchantApiToken</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">ODERO_MERCHANT_TOKEN</span><span class="p">;</span><span class="w"> </span><span class="c1">// server-side secret</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">payload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">merchantId</span><span class="p">,</span>
<span class="w"> </span><span class="nx">amount</span><span class="o">:</span><span class="w"> </span><span class="mf">50.0</span><span class="p">,</span><span class="w"> </span><span class="c1">// major units (e.g. 50.00 RON)</span>
<span class="w"> </span><span class="nx">currency</span><span class="o">:</span><span class="w"> </span><span class="s1">'RON'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">extOrderId</span><span class="o">:</span><span class="w"> </span><span class="s1">'order-333abc'</span><span class="p">,</span><span class="w"> </span><span class="c1">// your own order reference</span>
<span class="w"> </span><span class="nx">extOrderUrl</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"> </span><span class="nx">returnUrl</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"> </span><span class="nx">successUrl</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span><span class="w"> </span><span class="nx">failUrl</span><span class="o">:</span><span class="w"> </span><span class="s1">''</span><span class="p">,</span>
<span class="w"> </span><span class="nx">saveCard</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nx">recurring</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nx">submerchants</span><span class="o">:</span><span class="w"> </span><span class="p">[{</span>
<span class="w"> </span><span class="nx">extId</span><span class="o">:</span><span class="w"> </span><span class="nx">merchantId</span><span class="p">,</span>
<span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">'My Store'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">amount</span><span class="o">:</span><span class="w"> </span><span class="mf">50.0</span><span class="p">,</span>
<span class="w"> </span><span class="nx">products</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">extId</span><span class="o">:</span><span class="w"> </span><span class="s1">'0'</span><span class="p">,</span><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s1">'T-Shirt'</span><span class="p">,</span><span class="w"> </span><span class="nx">price</span><span class="o">:</span><span class="w"> </span><span class="mf">50.0</span><span class="p">,</span><span class="w"> </span><span class="nx">quantity</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="nx">total</span><span class="o">:</span><span class="w"> </span><span class="mf">50.0</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">}],</span>
<span class="w"> </span><span class="c1">// Optional: pre-fill the buyer. Include only if email+phone+country+city+address</span>
<span class="w"> </span><span class="c1">// are all set, otherwise leave null and the sheet will ask for them.</span>
<span class="w"> </span><span class="nx">customer</span><span class="o">:</span><span class="w"> </span><span class="kc">null</span>
<span class="p">};</span>
<span class="c1">// Step 1: sign the payload</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">sig</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">fetch</span><span class="p">(</span><span class="nx">BASE</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">'util/merchant-signature-header-json'</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">method</span><span class="o">:</span><span class="w"> </span><span class="s1">'POST'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">headers</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s1">'Content-Type'</span><span class="o">:</span><span class="w"> </span><span class="s1">'application/json'</span><span class="p">,</span><span class="w"> </span><span class="s1">'X-Requested-With'</span><span class="o">:</span><span class="w"> </span><span class="s1">'XMLHttpRequest'</span><span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">body</span><span class="o">:</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span><span class="w"> </span><span class="nx">merchantId</span><span class="p">,</span><span class="w"> </span><span class="nx">merchantApiToken</span><span class="p">,</span><span class="w"> </span><span class="nx">payload</span><span class="w"> </span><span class="p">})</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">json</span><span class="p">());</span><span class="w"> </span><span class="c1">// => { merchant_signature }</span>
<span class="c1">// Step 2: create the session</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">session</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">fetch</span><span class="p">(</span><span class="nx">BASE</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">'api/payments/session'</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">method</span><span class="o">:</span><span class="w"> </span><span class="s1">'POST'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">headers</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s1">'Content-Type'</span><span class="o">:</span><span class="w"> </span><span class="s1">'application/json'</span><span class="p">,</span><span class="w"> </span><span class="s1">'X-MERCHANT-SIGNATURE'</span><span class="o">:</span><span class="w"> </span><span class="nx">sig</span><span class="p">.</span><span class="nx">merchant_signature</span><span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">body</span><span class="o">:</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">payload</span><span class="p">)</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="nx">r</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="nx">r</span><span class="p">.</span><span class="nx">json</span><span class="p">());</span><span class="w"> </span><span class="c1">// => { sessionId, message }</span>
<span class="k">return</span><span class="w"> </span><span class="nx">session</span><span class="p">.</span><span class="nx">sessionId</span><span class="p">;</span><span class="w"> </span><span class="c1">// hand this to the app</span></code></pre></div>
<p><strong>Which methods the sheet offers</strong> is decided by the session, not
the app. When the SDK loads the session it reads an
<code style="white-space: nowrap">availablePaymentMethods</code> list
(<code style="white-space: nowrap">card</code>,
<code style="white-space: nowrap">apple_pay</code>,
<code style="white-space: nowrap">google_pay</code>) configured on your Odero
merchant, and shows the wallet buttons only for the methods it contains. See
<a href="#in-app-payment-types">Payment types</a>.</p>
<p>
Once your backend returns a <code style="white-space: nowrap">sessionId</code>,
move on to your platform:
<a href="#in-app-ios">iOS</a>, <a href="#in-app-android">Android</a> or
<a href="#in-app-react-native">React Native</a>.
</p>
</div>
<h2 id='in-app-payment-types'>Payment types</h2>
<div class="content">
<p>
The same payment sheet handles every method. What it shows for a given checkout
is driven by the <strong>session</strong> (the
<code style="white-space: nowrap">availablePaymentMethods</code> configured on
your Odero merchant) and by what you pass to
<code style="white-space: nowrap">showPaymentSheet</code>.
</p>
<table>
<thead>
<tr><th>Method</th><th>iOS</th><th>Android</th><th>React Native</th><th>Shown when</th></tr>
</thead>
<tbody>
<tr>
<td>Card (new card)</td>
<td>Yes</td><td>Yes</td><td>Yes</td>
<td>Always</td>
</tr>
<tr>
<td>Saved / stored card</td>
<td>Yes</td><td>Yes</td><td>Yes</td>
<td>You pass <code style="white-space: nowrap">savedCards</code></td>
</tr>
<tr>
<td>Apple Pay</td>
<td>Yes</td><td>—</td><td>iOS only</td>
<td>Session allows <code style="white-space: nowrap">apple_pay</code> (+ wallet set up)</td>
</tr>
<tr>
<td>Google Pay</td>
<td>—</td><td>Yes</td><td>Android only</td>
<td>Session allows <code style="white-space: nowrap">google_pay</code> (+ wallet set up)</td>
</tr>
</tbody>
</table>
<h3>Card</h3>
<p>
The default method, always available. The customer enters card number, expiry,
CVC and cardholder name with live validation (Luhn check, brand detection,
MM/YY mask). Submitted internally as
<code style="white-space: nowrap">card</code>.
</p>
<h3>Saved card</h3>
<p>
Offer previously tokenized cards for one-tap payment. You pass a list of saved
cards to <code style="white-space: nowrap">showPaymentSheet</code>; the customer
picks one and re-enters only the CVC. Submitted as
<code style="white-space: nowrap">stored_card</code> using the card's
<code style="white-space: nowrap">cardToken</code>. Each saved card carries:
</p>
<ul>
<li><code style="white-space: nowrap">cardToken</code>: the stored-card token from Odero.</li>
<li><code style="white-space: nowrap">lastFourDigits</code>, <code style="white-space: nowrap">expirationMonth</code>, <code style="white-space: nowrap">expirationYear</code>: for display.</li>
<li><code style="white-space: nowrap">cvv</code>: may be blank; the sheet asks for it on the Enter-CVC step.</li>
</ul>
<h3>Apple Pay (iOS)</h3>
<p>
Shown when the session allows <code style="white-space: nowrap">apple_pay</code>
and the device can pay. The SDK builds a
<code style="white-space: nowrap">PKPaymentRequest</code> with your
<code style="white-space: nowrap">applePayMerchantId</code> (Visa + Mastercard,
3-D Secure capability) and forwards the encrypted token to Odero (gateway
<code style="white-space: nowrap">oderopay</code>). Requires the Apple Pay
entitlement and that your merchant certificate is uploaded to Odero. See
<a href="#in-app-merchant-setup">Merchant setup</a>.
</p>
<h3>Google Pay (Android)</h3>
<p>
Shown when the session allows <code style="white-space: nowrap">google_pay</code>
and Google Pay is ready on the device. Uses Google Play Services Wallet
with tokenization gateway <code style="white-space: nowrap">oderopay</code> and
your Odero merchant id as the <code style="white-space: nowrap">gatewayMerchantId</code>
(Visa + Mastercard, <code style="white-space: nowrap">PAN_ONLY</code> +
<code style="white-space: nowrap">CRYPTOGRAM_3DS</code>). The wallet environment
follows the API environment (DEV → test, PROD → production).
</p>
<h3>3-D Secure</h3>
<p>
Any card or wallet payment can trigger a 3-D Secure challenge. The SDK
handles it for you: it opens the bank's page in an in-sheet web view and closes
it automatically when the challenge completes. No integrator code is needed.
</p>
<h3>Billing / customer information</h3>
<p>
If the session does not already carry the buyer's details, the sheet collects
billing/contact fields (email, phone, country, city, address) before paying. If
you included a <code style="white-space: nowrap">customer</code> when you created
the session, these fields are skipped.
</p>
</div>
<h2 id='in-app-ios'>iOS</h2>
<div class="content">
<p>
The iOS SDK is <code style="white-space: nowrap">OderoPaySDKIOS</code>, a binary
xcframework delivered through CocoaPods. You instantiate
<code style="white-space: nowrap">OderoPaySDK</code>, call
<code style="white-space: nowrap">showPaymentSheet</code> with a
<code style="white-space: nowrap">sessionId</code>, and observe the result via
<code style="white-space: nowrap">NotificationCenter</code>.
</p>
<h3>Install</h3>
<p>Reference the published podspec from Odero's Artifactory in your
<code style="white-space: nowrap">Podfile</code>:</p>
<blockquote><p>Podfile</p></blockquote>
<div class="highlight"><pre class="highlight ruby tab-ruby"><code><span class="n">platform</span><span class="w"> </span><span class="ss">:ios</span><span class="p">,</span><span class="w"> </span><span class="s1">'15.0'</span>
<span class="n">target</span><span class="w"> </span><span class="s1">'YourApp'</span><span class="w"> </span><span class="k">do</span>
<span class="w"> </span><span class="n">use_frameworks!</span>
<span class="w"> </span><span class="n">pod</span><span class="w"> </span><span class="s1">'OderoPaySDKIOS'</span><span class="p">,</span>
<span class="w"> </span><span class="ss">:podspec</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="s1">'https://ro-artifactory.devtokeninc.com/artifactory/PublicLibraries/Odero/oderopaysdk/oderopaysdkios/1.0.0/OderoPaySDKIOS.podspec'</span>
<span class="k">end</span></code></pre></div>
<p>Then <code style="white-space: nowrap">pod install</code> and open the generated
<code style="white-space: nowrap">.xcworkspace</code>.</p>
<h3>Project setup</h3>
<p><strong>1. Select the environment with an <code style="white-space: nowrap">sdk.plist</code>.</strong>
Add a file named exactly <code style="white-space: nowrap">sdk.plist</code> to your
app bundle with an <code style="white-space: nowrap">ENV</code> key. The SDK reads
it at init: <code style="white-space: nowrap">"DEV"</code> selects DEV, anything
else (or a missing file) selects PROD.</p>
<blockquote><p>sdk.plist</p></blockquote>
<div class="highlight"><pre class="highlight xml tab-xml"><code><span class="nt"><dict></span>
<span class="w"> </span><span class="nt"><key></span>ENV<span class="nt"></key></span>
<span class="w"> </span><span class="nt"><string></span>DEV<span class="nt"></string></span>
<span class="nt"></dict></span></code></pre></div>
<p><strong>2. Apple Pay entitlement (only if you offer Apple Pay).</strong>
In Xcode → Signing & Capabilities add the <strong>Apple Pay</strong>
capability and your merchant id. The id here must match the
<code style="white-space: nowrap">applePayMerchantId</code> you pass to