-
Notifications
You must be signed in to change notification settings - Fork 1
/
iamport-naverpay.php
2546 lines (2085 loc) · 105 KB
/
iamport-naverpay.php
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
<?php
class WC_Gateway_Iamport_NaverPay extends Base_Gateway_Iamport {
const GATEWAY_ID = 'iamport_naverpay';
const PLUGIN_EXTRA_PRODUCT_OPTION = 'thwepof';
const OPTION_EXTRA_PRODUCT_OPTION = 'thwepof_options';
const PLUGIN_TM_EXTRA_PRODUCT_OPTION = 'tmextra';
const OPTION_TM_EXTRA_PRODUCT_OPTION = 'tmdata';
const OPTION_TM_EXTRA_PRODUCT_OPTION_REPO = 'tmcartepo';
const PLUGIN_YITH_PRODUCT_OPTION = 'yith';
const OPTION_YITH_PRODUCT_OPTION = 'yith_wapo_options';
//WooShipping => Naver
private $logisCompany = array(
'fedex' => 'FEDEX', //Fedex
'ems' => 'EMS', //우체국EMS
'CVSnet' => 'CVSNET', // 편의점
'ilyanglogis' => 'ILYANG', //일양로지스
'kgbls' => 'KGB', //KGB택배
'ocskorea' => 'CH1', // OCS코리아
'dhl' => 'DHL', //DHL
'ups' => 'UPS', //UPS
'tnt' => 'TNT', //TNT익스프레스
'innogis' => 'INNOGIS', //GTX 로지스
'epost' => 'EPOST', //우체국택배
'hlc' => 'HYUNDAI', //현대택배
'hanjin' => 'HANJIN', // 한진택배
'hanips' => 'HPL', // 한의사랑택배
'dongbuexpress' => 'DONGBU', //동부택배
'kdexp' => 'KDEXP', //경동택배
'kglogis' => 'DONGBU', //KG로지스
'epantos' => 'PANTOS', //범한판토스
'ilogen' => 'KGB', // 로젠택배
'koreanair' => 'KOREXG', //대한한공배송
'doortodoor' => 'CJGLS', // 대한통운
);
public function __construct() {
parent::__construct();
//settings
$this->title = __( '네이버페이', 'iamport-for-woocommerce' );
$this->method_title = __( '아임포트(네이버페이)', 'iamport-for-woocommerce' );
$this->method_description = __( '=> 아임포트 서비스를 이용해 네이버페이를 연동할 수 있습니다. <strong style="background:#ccc"><a href="http://www.iamport.kr/download/naverpay-woocommerce-manual.pdf" target="iamport-woocommerce-manual">[우커머스-네이버페이 설정관련 매뉴얼보기]</a></strong><br>=> [아임포트] X PG사 제휴할인혜택을 받아보세요! <a href="http://www.iamport.kr/pg#promotion" target="_blank">PG 신규계약 프로모션 안내</a><br>=> 아임포트의 최신 공지사항도 놓치지 마세요! <a href="http://www.iamport.kr/notice" target="_blank">공지사항보기</a>', 'iamport-for-woocommerce' );
$this->has_fields = true;
$this->supports = array( 'products' );
add_action( 'woocommerce_api_naver-product-info', array( $this, 'naverProductsAsXml' ) );
add_action( 'woocommerce_api_iamport-naver-product-xml', array( $this, 'naverProductsAsXml' ) );
add_filter( 'woocommerce_available_payment_gateways', array($this, 'eliminateMySelf') );
add_filter( 'woocommerce_cancel_unpaid_order', array($this, 'can_clear_unpaid_order'), 10, 2);
add_action( "iamport_naverpay_sync_review", array($this, "sync_review") );
//shipping tel 추가
add_filter( "woocommerce_admin_shipping_fields" , array($this, "admin_shipping_fields") );
//과거 구매평 동기화 기능
add_action( 'wp_ajax_iamport_naver_review_sync', array($this, 'ajax_naver_review_sync') );
//shipping정보 네이버 연동
add_action( 'wooshipping_delivery_order_items_sended', array($this, 'wooshipping_sended'), 10, 4 );
}
public function wooshipping_sended($order, $new_item_names, $company_id, $tracking_no)
{
if ($this->is_available()) { //네이버페이 Gateway 활성화인지
if ($order->get_payment_method() == self::GATEWAY_ID) { //네이버페이 Gateway 로 처리된 주문만
$impUid = $order->get_transaction_id();
if ($impUid) {
require_once(dirname(__FILE__).'/lib/iamport.php');
$iamport = new WooIamport($this->imp_rest_key, $this->imp_rest_secret);
$company = array_key_exists($company_id, $this->logisCompany) ? $this->logisCompany[$company_id] : 'CH1';
$result = $iamport->postNaverShipping($impUid, $company, $tracking_no);
if ($result->success) {
$order->add_order_note(sprintf( __( '네이버페이에 배송정보가 접수되었습니다.(아임포트 거래번호 : %s)', 'iamport-for-woocommerce' ), $impUid ));
} else {
$order->add_order_note(sprintf( __( '네이버페이에 배송정보 접수실패하였습니다.(아임포트 거래번호 : %s, 사유 : %s)', 'iamport-for-woocommerce' ), $impUid, $result->error['message'] ));
}
}
}
}
}
public function sync_review() {
$turnedOn = isset($this->settings["sync_review"]) && filter_var($this->settings["sync_review"], FILTER_VALIDATE_BOOLEAN);
if ( !$turnedOn ) return;
$now = time();
$last_executed = get_option("iamport_naverpay_sync_review_last_executed", 0);
if ( $last_executed == 0 ) $last_executed = $now - 24*60*60; //하루 전부터 가져오기 시작
if ( $now - $last_executed < 5*60 ) return; //5분 이내이면 중단
update_option("iamport_naverpay_sync_review_last_executed", $now);
$this->do_sync_review($last_executed);
}
public function generate_naver_review_sync_html($key, $config) {
$sanitizedID = esc_attr( $key );
$fromID = $sanitizedID . "-from";
$toID = $sanitizedID . "-to";
$buttonID = $sanitizedID . "-button";
ob_start();
?>
<tr valign="top">
<th scope="row" class="titledesc">
<label for="<?=$fromID?>"><?=esc_html( $config['title'] )?></label>
</th>
<td class="forminp">
<input type="date" style="width:180px" id="<?=$fromID?>" value="<?=date('Y-m-d')?>"> (00:00:00) 부터
<input type="date" style="width:180px" id="<?=$toID?>" value="<?=date('Y-m-d')?>"> (23:59:59) 까지
<button id="<?=$buttonID?>" class="button" href="#"><?=__( '동기화', 'iamport-for-woocommerce' )?></button>
<p class="description"><?=$config["description"]?></p>
<script type="text/javascript">
jQuery("#<?=$buttonID?>").click(function() {
var from = moment( jQuery("#<?=$fromID?>").val() ),
to = moment( jQuery("#<?=$toID?>").val() );
if ( !from.isValid() ) return alert("시작 일자가 유효하지 않습니다.");
if ( !to.isValid() ) return alert("종료 일자가 유효하지 않습니다.");
from = from.startOf("day");
to = to.endOf("day").set("millisecond", 0); //millisecond까지 endOf로 바뀌므로 0으로 바꿔야 함
var tomorrow = moment().add(1, "day").startOf("day");
if ( tomorrow.diff(to, "second") < 0 ) return alert("종료 일자는 오늘보다 미래일자일 수 없습니다.");
var diffInMonth = to.diff(from, 'months'),
diffInDay = to.diff(from, 'second');
if ( diffInMonth > 0 ) return alert("한 번에 최대 1개월까지 동기화가 가능합니다.");
if ( diffInDay < 0 ) return alert("시작 일자는 종료 일자와 같거나 작아야 합니다.");
var data = {
action: "iamport_naver_review_sync",
from: from.format("YYYY-MM-DD"),
to: to.format("YYYY-MM-DD")
};
var that = this;
that.disabled = true;
jQuery(that).html("동기화 중 ...");
jQuery.post(ajaxurl, data, function(rsp) {
that.disabled = false;
jQuery(that).html("동기화");
if ( rsp.ok === true ) {
alert("동기화가 완료되었습니다.");
} else {
alert(rsp.error)
}
});
});
</script>
</td>
</tr>
<?php
return ob_get_clean();
}
public function ajax_naver_review_sync() {
header('Content-type: application/json');
if ( empty($_POST["from"]) || empty($_POST["to"]) ) {
echo json_encode(array(
"error" => "기간을 지정해야 합니다."
));
wp_die();
}
$offset = 9 * HOUR_IN_SECONDS; // Seoul
$from = strtotime($_POST["from"] . " 00:00:00"); //YYYY-MM-DD
$to = strtotime($_POST["to"] . " 23:59:59"); //YYYY-MM-DD
if ( $from === false || $to === false || $from >= $to ) {
echo json_encode(array(
"error" => "기간 범위가 유효하지 않습니다."
));
wp_die();
}
//1개월 초과 체크
/*
-1 month 는 31일인 경우 전월 30일을 찾지 못하여 문제가 됨 ( ex. 7월 31 기준으로 -1 month 하면 7월 1일이 반환됨 )
$monthAgo = strtotime("-1 month", $to);
if ( $from < $monthAgo ) {
echo json_encode(array(
"error" => "기간은 최대 1개월로 제한됩니다."
));
wp_die();
}
*/
//최대 31일이 넘는지만 체크
if ( ($to - $from) > 31*24*60*60 ) {
echo json_encode(array(
"error" => "기간은 최대 1개월로 제한됩니다."
));
wp_die();
}
$from = $from - $offset;
$to = min(time(), $to - $offset);
$this->do_sync_review($from, $to);
echo json_encode(array(
"ok" => true,
));
wp_die();
}
private function do_sync_review($fromInUTC, $toInUTC=null) { //fromInUTC : timestamp
require_once(dirname(__FILE__).'/lib/iamport.php');
$iamport = new WooIamport($this->imp_rest_key, $this->imp_rest_secret);
$safe_break = 10;
$interval = 24*60*60;
$offset = 9 * HOUR_IN_SECONDS; // Seoul
$zoneOffsetHour = get_option( 'gmt_offset' );
$nowInUTC = time();
if ( $toInUTC == null ) $toInUTC = $nowInUTC;
$generalReviews = array();
$premiumReviews = array();
while ($fromInUTC < $toInUTC && --$safe_break >= 0) {
$fromDT = new DateTime();
$fromDT->setTimestamp( $fromInUTC ); //offset 을 더하지 않고 보내야 함
$toDT = new DateTime();
$toDT->setTimestamp( min($fromInUTC+$interval, $nowInUTC) ); //offset 을 더하지 않고 보내야 함
$result = $iamport->getNaverReviews($fromDT, $toDT, "general");
if ( $result->success ) {
$generalReviews = array_merge($generalReviews, $result->data);
}
usleep(300);
$result = $iamport->getNaverReviews($fromDT, $toDT, "premium");
if ( $result->success ) {
$premiumReviews = array_merge($premiumReviews, $result->data);
}
usleep(300);
$fromInUTC += $interval;
}
//product_id 기준으로 그루핑
$productCommentsMap = array();
$allReviews = array_merge($generalReviews, $premiumReviews);
foreach ($allReviews as $rev) {
$productId = $rev->product_id;
if ( !isset($productCommentsMap[ $productId ]) ) $productCommentsMap[ $productId ] = array();
$productCommentsMap[ $productId ][] = $rev;
}
foreach ($productCommentsMap as $productId => $reviews) {
// The Query
$writtenComments = get_comments(array(
"post_id" => $productId,
"meta_query" => array(
"key" => "review_id",
"value" => array_map(function($t){ return $t->review_id; }, $allReviews),
"compare" => "EXISTS"
)
));
$writtenIds = array();
foreach ($writtenComments as $wc) {
$writtenIds[] = get_comment_meta($wc->comment_ID, "review_id", true);
}
foreach ($reviews as $rev) {
if ( !in_array($rev->review_id, $writtenIds) ) {
wp_insert_comment(array(
"comment_post_ID" => $productId,
"comment_author" => $rev->writer,
"comment_content" => $rev->content ? sprintf("[%s] %s", $rev->title, $rev->content) : $rev->title,
"comment_date" => date("Y-m-d H:i:s", $rev->created_at + $zoneOffsetHour * HOUR_IN_SECONDS),
"comment_date_gmt" => date("Y-m-d H:i:s", $rev->created_at),
"comment_type" => "review",
"comment_meta" => array(
"review_id" => $rev->review_id,
"rating" => $rev->score, //[2018-11-15] 일반/프리미엄 구매평 score 체계 통일 됨 (1 ~ 5)
// "rating" => $rev->content ? /*premium*/$rev->score - 8 : /*general*/($rev->score+1)*2 - 1,
)
));
}
}
}
}
public function eliminateMySelf($gateways) {
if ( is_checkout() ) unset($gateways[ $this->get_gateway_id() ]); //checkout 페이지에서 네이버페이 결제수단 노출되지 않도록 수정
return $gateways;
}
public function admin_shipping_fields($fields) {
if ( !isset($fields['phone1']) ) {
$fields['phone1'] = array(
'label' => __( '배송지 전화번호 1', 'iamport-for-woocommerce' ),
);
}
if ( !isset($fields['phone2']) ) {
$fields['phone2'] = array(
'label' => __( '배송지 전화번호 2', 'iamport-for-woocommerce' ),
);
}
return $fields;
}
public function can_clear_unpaid_order($checkout_order_get_created_via, $order) {
if ( $checkout_order_get_created_via ) return true;
$pg_provider = get_post_meta($order->get_id(), '_iamport_provider', true);
return $pg_provider == "naverco";
}
protected function get_gateway_id() {
return self::GATEWAY_ID;
}
public function init_form_fields() {
parent::init_form_fields();
$allCategories = IamportHelper::get_all_categories();
$allProducts = IamportHelper::get_all_products();
//Shipping Zones
$zones = WC_Shipping_Zones::get_zones();
$zoneOptions = array();
foreach ($zones as $zoneId => $zone) {
$zoneOptions[$zoneId] = $zone['zone_name'];
}
$this->form_fields = array_merge( array(
// 'enabled' => array(
// 'title' => __( 'Enable/Disable', 'woocommerce' ),
// 'type' => 'checkbox',
// 'label' => __( '아임포트(네이버페이) 결제 사용', 'iamport-for-woocommerce' ),
// 'default' => 'yes'
// ),
// 'title' => array(
// 'title' => __( 'Title', 'woocommerce' ),
// 'type' => 'text',
// 'description' => __( '주문목록에 표시될 결제수단명', 'iamport-for-woocommerce' ),
// 'default' => __( '네이버페이', 'iamport-for-woocommerce' ),
// 'desc_tip' => true,
// ),
// 'description' => array(
// 'title' => __( 'Customer Message', 'woocommerce' ),
// 'type' => 'textarea',
// 'description' => __( '구매자에게 결제수단에 대한 상세설명을 합니다.', 'iamport-for-woocommerce' ),
// 'default' => __( '네이버페이 결제창으로 이동하여 결제를 진행하실 수 있습니다. 네이버페이 특성상, 결제정보를 동기화하는데 다소 시간이 소요될 수 있습니다(최대 1분). 결제정보 동기화가 완료되면 자동으로 우커머스 주문상태가 "결제완료됨"으로 변경됩니다.', 'iamport-for-woocommerce' )
// ),
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( '네이버페이 결제 사용', 'iamport-for-woocommerce' ),
'default' => 'yes'
),
'show_button' => array(
'title' => __( '네이버페이 구매버튼 보이기', 'iamport-for-woocommerce' ),
'description' => __( '상품페이지, 장바구니에 네이버페이 구매버튼을 출력할지 여부를 결정합니다.', 'iamport-for-woocommerce' ),
'type' => 'checkbox',
'label' => __( '네이버페이 구매버튼 보이기', 'iamport-for-woocommerce' ),
'default' => 'no'
),
'debug_mode' => array(
'title' => __( '네이버페이 검수모드', 'iamport-for-woocommerce' ),
'description' => __( '네이버페이 검수단계에서는 일반 사용자에게 네이버페이 구매버튼이 보여지면 안됩니다. 위의 "네이버페이 구매버튼 보이기"는 체크해제하시고 "네이버페이 검수모드"만 체크해주세요. 네이버페이 검수팀에는 URL파라메터로 "naver-debug=iamport"를 추가하면 네이버페이 버튼이 출력된다고 전달하시면 됩니다.', 'iamport-for-woocommerce' ),
'type' => 'checkbox',
'label' => __( '네이버페이 검수모드', 'iamport-for-woocommerce' ),
'default' => 'no'
),
'sync_review' => array(
'title' => __( '네이버페이 구매평 자동 동기화', 'iamport-for-woocommerce' ),
'description' => __( '네이버페이 구매자가 작성한 구매평을 일정 주기로 가져와 우커머스 상품리뷰창에 추가해줍니다.', 'iamport-for-woocommerce' ),
'type' => 'checkbox',
'label' => __( '네이버페이 구매평 자동 동기화', 'iamport-for-woocommerce' ),
'default' => 'no'
),
'sync_review_by_range' => array(
'title' => __( '네이버페이 구매평 동기화', 'iamport-for-woocommerce' ),
'description' => __( '특정 기간에 대하여 네이버페이 구매평 동기화를 진행할 수 있습니다.(한 번에 최대 1개월) 여러 번 동기화를 하더라도 이미 등록된 구매평에 대해서는 추가등록되지 않습니다. 기간이 긴 경우 다소 시간이 소요됩니다.', 'iamport-for-woocommerce' ),
'type' => 'naver_review_sync',
'label' => 'xxxx'
),
'show_button_on_categories' => array(
'title' => __( '네이버페이 구매버튼을 출력할 상품카테고리', 'iamport-for-woocommerce' ),
'description' => __( '"네이버페이 구매버튼 보이기"가 체크되어있을 때, 일부 상품 카테고리에만 네이버페이 구매버튼을 출력하도록 설정할 수 있습니다.', 'iamport-for-woocommerce' ),
'type' => 'multiselect',
'options' => array('all'=>__('[모든 카테고리]', 'iamport-for-woocommerce')) + $allCategories,
'default' => 'all',
),
'disable_button_on_categories' => array(
'title' => __( '네이버페이 구매버튼을 비활성화시킬 상품카테고리', 'iamport-for-woocommerce' ),
'description' => __( '일부 상품 카테고리에만 네이버페이 구매버튼을 비활성상태로 출력하도록 설정할 수 있습니다.', 'iamport-for-woocommerce' ),
'type' => 'multiselect',
'options' => array('none'=>__('[비활성화할 카테고리 없음]', 'iamport-for-woocommerce'), 'all'=>__('[모든 카테고리]', 'iamport-for-woocommerce')) + $allCategories,
'default' => 'none',
),
'calc_shipping_tax' => array(
'title' => __( '네이버페이 배송비 부가세 추가', 'iamport-for-woocommerce' ),
'description' => __( '고정요금 배송비가 적용될 때, [세금상태] 값이 [과세가능]인 경우 입력된 배송비에 10%부가세를 추가하여 네이버페이에 청구합니다.', 'iamport-for-woocommerce' ),
'type' => 'checkbox',
'label' => __( '네이버페이 배송비 부가세 추가', 'iamport-for-woocommerce' ),
'default' => 'no'
),
'shipping_zone' => array(
'title' => __( '네이버페이 배송방법 적용될 배송구역', 'iamport-for-woocommerce' ),
'type' => 'select',
'default' => '0',
'options' => array(
'0' => __('Locations not covered by your other zones', 'woocommerce'),
) + $zoneOptions,
),
'button_pc_style' => array(
'title' => __( '네이버페이 PC버튼 스타일', 'iamport-for-woocommerce' ),
'type' => 'select',
'default' => 'C2',
'options' => array(
'A' => 'A',
'B' => 'B',
'C1' => 'C1',
'C2' => 'C2',
'C3' => 'C3',
'D1' => 'D1',
'D2' => 'D2',
'D3' => 'D3',
'E1' => 'E1',
'E2' => 'E2',
'E3' => 'E3',
)
),
'button_mobile_style' => array(
'title' => __( '네이버페이 모바일버튼 스타일', 'iamport-for-woocommerce' ),
'type' => 'select',
'default' => 'MA',
'options' => array(
'MA' => 'MA',
'MB' => 'MB',
)
),
'button_position_on_product' => array(
'title' => __( '상품페이지 내 네이버페이 버튼 위치', 'iamport-for-woocommerce' ),
'type' => 'select',
'default' => 'below',
'options' => array(
'below' => '장바구니버튼의 아래 라인',
'after' => '장바구니버튼과 동일 라인(오른쪽)',
)
),
'button_position_on_cart' => array(
'title' => __( '장바구니페이지 내 네이버페이 버튼 위치', 'iamport-for-woocommerce' ),
'type' => 'select',
'default' => 'above',
'options' => array(
'above' => '체크아웃버튼 위',
'below' => '체크아웃버튼 아래',
)
),
'button_key' => array(
'title' => __( '네이버페이 구매버튼 생성키', 'iamport-for-woocommerce' ),
'type' => 'text',
'description' => __( '네이버페이에서 발급된 버튼 생성 키를 입력해주세요.', 'iamport-for-woocommerce' ),
'label' => __( '네이버페이 구매버튼 생성키', 'iamport-for-woocommerce' ),
),
'pg_id' => array(
'title' => __( '네이버페이 파트너 ID', 'woocommerce' ),
'type' => 'text',
'description' => __( '하나의 아임포트 계정에 여러 개의 네이버페이 파트너 ID를 설정한 경우, 사용될 네이버 파트너 ID를 특정할 수 있습니다.', 'iamport-for-woocommerce' ),
),
'inflow_account' => array(
'title' => __( '네이버 유입경로 분석 계정', 'iamport-for-woocommerce' ),
'type' => 'text',
'description' => __( '네이버페이센터 가입 시 네이버로부터 이메일로 전달된 "네이버공통인증키"입니다. "가맹점센터(네이버페이센터)>내정보>가맹점가입정보>쇼핑몰정보" 에서 유입경로 Account ID와 같습니다.', 'iamport-for-woocommerce' ),
'label' => __( '네이버 유입경로 분석 계정', 'iamport-for-woocommerce' ),
),
'default_css' => array(
'title' => __( '네이버페이 버튼 관련 기본 CSS', 'iamport-for-woocommerce' ),
'type' => 'textarea',
'default' => '.iamport-naverpay-container { }
.iamport-naverpay-product-button {padding:15px 0;text-align:right;}
#iamport-naverpay-cart-button {padding:15px 0;text-align:right;}',
'label' => __( '네이버페이 버튼 관련 기본 CSS', 'iamport-for-woocommerce' ),
),
'culture_products' => array(
'title' => __( '도서공연비 소득공제대상 (상품)', 'iamport-for-woocommerce' ),
'type' => 'multiselect',
'default' => 'none',
'description' => __( '문화체육관광부의 도서공연비 소득공제대상 상품을 선택해주세요. 선택된 상품 또는 아래 선택된 카테고리에 해당되는 경우 소득공제주문으로 적용됩니다. 소득공제대상 상품과 비대상 상품의 혼합결제는 불가능합니다.' ),
'options' => array(
"none" => "[적용대상없음]",
"all" => "[모든 상품]",
) + $allProducts,
),
'culture_categories' => array(
'title' => __( '도서공연비 소득공제대상 (카테고리)', 'iamport-for-woocommerce' ),
'type' => 'multiselect',
'default' => 'none',
'description' => __( '문화체육관광부의 도서공연비 소득공제대상 상품을 선택해주세요. 선택된 카테고리 또는 위에서 선택된 상품에 해당되는 경우 소득공제주문으로 적용됩니다. 소득공제대상 상품과 비대상 상품의 혼합결제는 불가능합니다.' ),
'options' => array(
"none" => "[적용대상없음]",
"all" => "[모든 카테고리]",
) + $allCategories,
)
), $this->form_fields);
}
/**
*
* Override
*
*/
public function process_admin_options() {
$post_data = $this->get_post_data();
$key = $this->get_field_key("sync_review");
if ( isset($post_data[$key]) && filter_var($post_data[$key], FILTER_VALIDATE_BOOLEAN) === true ) { //turn on
wp_schedule_event(time(), "hourly", "iamport_naverpay_sync_review");
} else { //turn off
$timestamp = wp_next_scheduled( 'iamport_naverpay_sync_review' );
wp_unschedule_event( $timestamp, 'iamport_naverpay_sync_review' );
}
parent::process_admin_options();
}
public function get_user_code() {
if ( !isset($this->settings['imp_user_code']) ) return "";
return $this->settings['imp_user_code'];
}
public function get_button_key() {
if ( !isset($this->settings['button_key']) ) return "";
return $this->settings['button_key'];
}
public function can_show_button() {
return $this->enabled == "yes" && (isset($this->settings['show_button']) && $this->settings['show_button'] === "yes") || (isset($this->settings['debug_mode']) && $this->settings['debug_mode'] === "yes" && isset($_GET["naver-debug"]) && $_GET["naver-debug"] === "iamport");
}
public function is_debug_mode() {
return isset($this->settings['debug_mode']) && $this->settings['debug_mode'] === "yes";
}
public function get_display_categories() {
if ( !isset($this->settings['show_button_on_categories']) ) return array();
$categories = $this->settings['show_button_on_categories'];
if ( $categories === 'all' || ( is_array($categories) && in_array('all', $categories) ) ) return 'all';
return $categories;
}
public function get_disabled_categories() {
if ( !isset($this->settings['disable_button_on_categories']) ) return array();
$categories = $this->settings['disable_button_on_categories'];
if ( $categories === 'all' || ( is_array($categories) && in_array('all', $categories) ) ) return 'all';
if ( $categories === 'none' || ( is_array($categories) && in_array('none', $categories) ) ) return array();
return $categories;
}
public function get_attribute($key) {
if ( !in_array($key, array("calc_shipping_tax", "shipping_zone", "button_pc_style", "button_mobile_style", "button_position_on_product", "button_position_on_cart", "inflow_account", "default_css", "culture_products", "culture_categories", "pg_id")) ) return null;
$value = isset($this->settings[$key]) ? $this->settings[$key] : null;
if ( $value == null && isset($this->form_fields[$key]['default']) ) $value = $this->form_fields[$key]['default'];
return $value;
}
public function iamport_order_detail( $order_id ) {
global $woocommerce;
//TODO
$naverPayLink = get_post_meta($order_id, '_iamport_naverpay_paylink', true);
ob_start();
?>
<h2><?=__( '결제 상세', 'iamport-for-woocommerce' )?></h2>
<table class="shop_table order_details">
<tbody>
<tr>
<th><?=__( '결제수단', 'iamport-for-woocommerce' )?></th>
<td><?=__( '네이버페이', 'iamport-for-woocommerce')?></td>
</tr>
</tbody>
</table>
<?php
ob_end_flush();
}
public function is_paid_confirmed($order, $payment_data) {
add_action( 'iamport_pre_order_completed', array($this, 'update_shipping_amount'), 10, 2 ); //불필요하게 hook이 많이 걸리지 않도록(naver-gateway객체를 여러 군데에서 생성한다.)
return $payment_data->status === 'paid'; //이미 paid인 건에 대해서만 is_paid_confirmed가 호출되기는 하지만 한 번 더 체크
}
public function update_shipping_info($order, $payment_data) {
try {
// 네이버페이 상품주문정보 조회
$impUid = $payment_data->imp_uid;
$iamport = new WooIamport($this->imp_rest_key, $this->imp_rest_secret);
$result = $iamport->getNaverProductOrders($impUid);
if ( $result->success ) {
$productOrders = $result->data;
$shippingNotes = array();
foreach ($productOrders as $idx=>$po) {
//product line item
$productLineItem = IamportHelper::findProductItem($order, $po->product_id, self::getVariationIdFromQuery($po->product_option_id), self::getAttributesFromQuery($po->product_option_id));
if ($productLineItem) {
$productLineItem->add_meta_data('naver_product_order_id', $po->product_order_id);
$productLineItem->add_meta_data('naver_product_order_status', $po->product_order_status);
$productLineItem->add_meta_data('product_amount', $po->product_amount);
$productLineItem->add_meta_data('delivery_amount', $po->delivery_amount);
$productLineItem->add_meta_data('shipping_memo', $po->shipping_memo ? $po->shipping_memo : '없음');
$productLineItem->add_meta_data('shipping_due', $po->shipping_due ? date('Y-m-d H:i:s', $po->shipping_due + get_option('gmt_offset')*HOUR_IN_SECONDS) : '없음');
$productLineItem->save_meta_data();
}
$shippingNotes[] = sprintf( __( '[상품명 : %s] 배송요청사항 : %s (배송기한 : %s)', 'iamport-for-woocommerce' ),
$po->product_name,
$po->shipping_memo ? $po->shipping_memo : "없음",
$po->shipping_due ? date('Y-m-d H:i:s', $po->shipping_due + get_option('gmt_offset')*HOUR_IN_SECONDS) : "없음");
if ( $idx == 0 ) { //첫번째 상품정보에서 orderer / shipping 정보 추출
if(!empty($order->get_shipping_address_1()) && ($order->get_shipping_address_1() != $po->shipping_address->base)) {
$order->add_order_note("네이버페이 배송지가 변경되었습니다.");
$order->update_status('address-changed');
}
$order->set_billing_first_name( $po->orderer->name );
$order->set_billing_email( $po->orderer->id . "@naver.com" );
$order->set_billing_phone( $po->orderer->tel );
$order->set_shipping_first_name( $po->shipping_address->name );
$order->add_meta_data( "_shipping_phone1", $po->shipping_address->tel1, true ); //구리지만 어쩔 수 없음
$order->add_meta_data( "_shipping_phone2", $po->shipping_address->tel2, true ); //구리지만 어쩔 수 없음
$order->set_shipping_address_1( $po->shipping_address->base );
$po->shipping_address->detail ? $order->set_shipping_address_2( $po->shipping_address->detail ) : $order->set_shipping_address_2("");
$order->set_shipping_postcode( $po->shipping_address->postcode );
}
}
$orderComment = implode(",\n", $shippingNotes);
$order->set_customer_note( $orderComment );
} else {
$order->add_order_note( '[네이버페이-상세조회실패] ' . $result->error['message'] );
error_log('[네이버페이-상세조회실패] ' . $result->error['message']);
}
} catch (Exception $e) {
$order->add_order_note( '[네이버페이-상세조회실패] ' . $e->getMessage() );
error_log($e);
}
}
public function update_shipping_amount($order, $payment_data) {
$shipping_amount = $payment_data->amount - $order->get_total();
if ( $shipping_amount > 0 ) $order->add_order_note( sprintf( __( '네이버페이 주문시 상품외 추가 배송비 결제가 이뤄졌습니다.(배송비 : %s원)', 'iamport-for-woocommerce' ), number_format($shipping_amount) ) );
$item = new WC_Order_Item_Shipping();
$item->set_props( array(
'method_title' => $shipping_amount > 0 ? "네이버페이 배송비":"무료배송",
'method_id' => 0,
'total' => wc_format_decimal( $shipping_amount ),
// 'taxes' => $shipping_rate->taxes,
'order_id' => $order->get_id(),
) );
// $item->add_meta_data( $key, $value, true ); (TODO : 배송비 항목 상품 추가하는 방법)
try {
// 네이버페이 상품주문정보 조회
$impUid = $payment_data->imp_uid;
$iamport = new WooIamport($this->imp_rest_key, $this->imp_rest_secret);
$result = $iamport->getNaverProductOrders($impUid);
if ( $result->success ) {
$productOrders = $result->data;
$shippingNotes = array();
foreach ($productOrders as $idx=>$po) {
//product line item
$productLineItem = IamportHelper::findProductItem($order, $po->product_id, self::getVariationIdFromQuery($po->product_option_id), self::getAttributesFromQuery($po->product_option_id));
if ($productLineItem) {
$productLineItem->add_meta_data('naver_product_order_id', $po->product_order_id);
$productLineItem->add_meta_data('naver_product_order_status', $po->product_order_status);
$productLineItem->add_meta_data('product_amount', $po->product_amount);
$productLineItem->add_meta_data('delivery_amount', $po->delivery_amount);
$productLineItem->add_meta_data('shipping_memo', $po->shipping_memo ? $po->shipping_memo : '없음');
$productLineItem->add_meta_data('shipping_due', $po->shipping_due ? date('Y-m-d H:i:s', $po->shipping_due + get_option('gmt_offset')*HOUR_IN_SECONDS) : '없음');
$productLineItem->save_meta_data();
}
//legacy
$shippingNotes[] = sprintf( __( '[상품명 : %s] 배송요청사항 : %s (배송기한 : %s)', 'iamport-for-woocommerce' ),
$po->product_name,
$po->shipping_memo ? $po->shipping_memo : "없음",
$po->shipping_due ? date('Y-m-d H:i:s', $po->shipping_due + get_option('gmt_offset')*HOUR_IN_SECONDS) : "없음");
if ( $idx == 0 ) { //첫번째 상품정보에서 orderer / shipping 정보 추출
$order->set_billing_first_name( $po->orderer->name );
$order->set_billing_email( $po->orderer->id . "@naver.com" );
$order->set_billing_phone( $po->orderer->tel );
$order->set_shipping_first_name( $po->shipping_address->name );
$order->add_meta_data( "_shipping_phone1", $po->shipping_address->tel1, true ); //구리지만 어쩔 수 없음
$order->add_meta_data( "_shipping_phone2", $po->shipping_address->tel2, true ); //구리지만 어쩔 수 없음
$order->set_shipping_address_1( $po->shipping_address->base );
$order->set_shipping_address_2( $po->shipping_address->detail );
$order->set_shipping_postcode( $po->shipping_address->postcode );
}
}
$orderComment = implode(",\n", $shippingNotes);
$order->add_order_note( $orderComment );
$order->set_customer_note( $orderComment );
} else {
$order->add_order_note( '[네이버페이-상세조회실패] ' . $result->error['message'] );
error_log('[네이버페이-상세조회실패] ' . $result->error['message']);
}
} catch (Exception $e) {
$order->add_order_note( '[네이버페이-상세조회실패] ' . $e->getMessage() );
error_log($e);
}
$item->save();
$order->add_item( $item );
$order->set_shipping_total( $shipping_amount ); //배송비 지정
$order->set_billing_address_1( $payment_data->buyer_addr );
$order->set_billing_postcode( $payment_data->buyer_postcode );
$order->set_total( $payment_data->amount );
$order->save();
}
public function naverProductsAsXml() {
require_once(dirname(__FILE__).'/lib/Array2xml.php');
require_once(dirname(__FILE__).'/includes/naver/NaverProduct.php');
require_once(dirname(__FILE__).'/includes/naver/NaverOptionItem.php');
require_once(dirname(__FILE__).'/includes/naver/NaverCombination.php');
require_once(dirname(__FILE__).'/includes/naver/NaverShippingPolicy.php');
/* 상품의 옵션을 조회해올 때
(
[0] => Array
(
[id] => XXX
[optionManageCodes] => X_X,X_X
[supplementIds] => XXX
)
)
*/
/* 본 상품만 조회할 때
(
[0] => Array
(
[id] => XXX
)
)
*/
$isSearchingOption = isset($_GET['optionSearch']) && filter_var($_GET['optionSearch'], FILTER_VALIDATE_BOOLEAN);
$isSearchingSupplement = isset($_GET['supplementSearch']) && filter_var($_GET['supplementSearch'], FILTER_VALIDATE_BOOLEAN);
$merchantCustomCode1 = isset($_GET['merchantCustomCode1']) ? intval($_GET['merchantCustomCode1']) : 0; //user ID
$refOrderId = isset($_GET['merchantCustomCode2']) ? wc_get_order_id_by_order_key($_GET['merchantCustomCode2']) : 0; //order key : 2.1.1 이전 버전에서는 없음
$queryProducts = isset($_GET['product']) ? $_GET['product'] : array();
$refOrder = new WC_Order($refOrderId);
WC()->session->set('chosen_shipping_methods', get_post_meta($refOrderId, '_chosen_shipping_methods', true));
if ($merchantCustomCode1 > 0 && IamportHelper::supportMembershipPlugin()) {
$loginId = $merchantCustomCode1;
$loginUser = get_user_by( 'id', $loginId );
if ($loginUser) {
wp_set_current_user($loginId); //가격계산을 위해 login 처리
//membership instance 다시 초기화
wc_memberships()->get_member_discounts_instance()->init();
}
}
$xmlProducts = array();
if ( $queryProducts ) {
$fakeCart = new WC_Cart();
$fakeCartMaxFee = 0;
foreach ($queryProducts as $p) {
$wooProduct = wc_get_product( $p['id'] );
$optionManageCodes = explode(",", $p['optionManageCodes']); // variation id를 optionManageCode로 사용
$naverProduct = new NaverProduct();
$naverProduct->id = $p['id'];
$naverProduct->name = $wooProduct->get_title(); //line_item의 name으로 사용됨
$naverProduct->taxType = $wooProduct->is_taxable() ? "TAX" : "TAX_FREE";
$naverProduct->basePrice = $wooProduct->get_price();
$naverProduct->infoUrl = get_post_permalink( $p['id'] );
$naverProduct->imageUrl = IamportNaverPayButton::getProductImageSrc($wooProduct);
$naverProduct->status = $wooProduct->is_purchasable() ? "ON_SALE" : "NOT_SALE";
$useWoocommerceShippingCalc = WC_Gateway_Iamport_NaverPay::useWoocommerceShippingCalc($p['id']); //parent product id
$calcShippingTax = filter_var($this->get_attribute('calc_shipping_tax'), FILTER_VALIDATE_BOOLEAN);
$defaultZoneId = intval($this->get_attribute('shipping_zone'));
$shippingMethods = WC_Gateway_Iamport_NaverPay::getShippingMethodsForProduct($wooProduct, $defaultZoneId); // 지정된 shipping method가 없으면 무료배송
$naverProduct->shippingPolicy = WC_Gateway_Iamport_NaverPay::toShippingPolicy($wooProduct, $shippingMethods, $calcShippingTax);
//3rd parth shipping policy 적용 후 surcharge 적용
if ( $isSearchingOption && $wooProduct->get_type() === "variable" ) {
/*
Array
(
[pa_color] => Array
(
[0] => red
[1] => blue
)
)
*/
$variations = $wooProduct->get_available_variations(); //옵션 조합
$attributes = $wooProduct->get_variation_attributes(); //선택가능한 옵션들
$variationPrices = $wooProduct->get_variation_prices(true); //낮은 가격순으로 정렬되어 있음
//optionItem
foreach ($attributes as $attribute_name => $options) {
$attribute_key = urldecode( $attribute_name ); //한글 encoding된 경우를 대비해 decode먼저 해줌
$optionItem = new NaverOptionItem("SELECT", wc_attribute_label( $attribute_key, $wooProduct ));
// $terms = wc_get_product_terms( $wooProduct->get_id(), $attribute_key, array( 'fields' => 'all' ) );
$terms = IamportNaverPayButton::get_product_attributes($wooProduct, $attribute_key);//term이 아닌 경우 대응
foreach ($terms as $term) {
$optionItem->addCase(IamportNaverPayButton::sanitize_slug_for_naver($term->slug), $term->name);
}
$naverProduct->addOptionItem($optionItem);
}
//combination
foreach($optionManageCodes as $optionCode) {
$variationId = self::getVariationIdFromQuery($optionCode);
$optionAttributes = self::getAttributesFromQuery($optionCode);
$variation = wc_get_product( $variationId );
if ( !$variation instanceof WC_Product_Variation ) {
continue;
}
if ( !$variation->variation_is_active() || !$variation->variation_is_visible() ) {
continue;
}
$combination = new NaverCombination($optionCode);
$combination->setPrice($variationPrices["price"][ $variationId ] - $wooProduct->get_price());
//attributes 의 loop 순서는 결제요청단계와 같으므로 $optionCode 를 | 구분자로 잘랐을 때 순서대로 매칭
$attrIndex = 0;
foreach ($attributes as $attribute_name => $options) {
if (!isset($optionAttributes[$attrIndex])) {
$attrIndex++;
continue;
}
$attribute_key = urldecode($attribute_name); //한글 encoding된 경우를 대비해 decode먼저 해줌
$terms = IamportNaverPayButton::get_product_attributes($wooProduct, $attribute_key);//term이 아닌 경우 대응
foreach ($terms as $term) {
$optionSlug = IamportNaverPayButton::sanitize_slug_for_naver($term->slug);
if ($optionSlug == $optionAttributes[$attrIndex]) {
$combination->addOption(wc_attribute_label($attribute_key, $wooProduct), $optionSlug);
}
}
$attrIndex++;
}
$naverProduct->addCombination($combination);
//우커머스 자체 배송비 계산
if ($useWoocommerceShippingCalc) {
$lineItem = IamportHelper::findProductItem($refOrder, $p['id'], $variationId);
if ($lineItem) {
$qty = $lineItem->get_quantity();
$internalShippingPolicy = WC_Gateway_Iamport_NaverPay::internalShippingPolicy($fakeCart, $p['id'], $qty, $variationId);
$naverProduct->shippingPolicy = $internalShippingPolicy;
$fakeCartMaxFee = max($fakeCartMaxFee, $internalShippingPolicy->getBaseFee());
}
}
}
} else {
if ($isSearchingOption) { //[2020-05-05] 3rd party product add on
foreach($optionManageCodes as $optionCode) {
if (self::isYITHOption($optionCode)) {
$itemId = intval( substr($optionCode, strlen(self::PLUGIN_YITH_PRODUCT_OPTION)) );
$productLineItem = $refOrder->get_item($itemId);
$productLineItem->read_meta_data();
$combination = new NaverCombination($optionCode);
$yithMeta = $productLineItem->get_meta(WC_Gateway_Iamport_NaverPay::OPTION_YITH_PRODUCT_OPTION);
if (!empty($yithMeta)) {
$yithOptionPrice = 0;
foreach($yithMeta as $yithOption) {
$optionItem = new NaverOptionItem("SELECT", $yithOption['name']);
$optionItem->addCase(IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($yithOption['value'])), $yithOption['value']);
$naverProduct->addOptionItem($optionItem);
$combination->addOption($yithOption['name'], IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($yithOption['value'])));
$yithOptionPrice += intval($yithOption['price']);
}
$combination->setPrice($yithOptionPrice);
$naverProduct->addCombination($combination);
}
} else if (self::isExtraProductOption($optionCode)) {
$itemId = intval( substr($optionCode, strlen(self::PLUGIN_EXTRA_PRODUCT_OPTION)) );
$productLineItem = $refOrder->get_item($itemId);
$productLineItem->read_meta_data();
$combination = new NaverCombination($optionCode);
$epMeta = $productLineItem->get_meta(self::OPTION_EXTRA_PRODUCT_OPTION);
if (!empty($epMeta)) {
foreach ($epMeta as $epName=>$epData) {
if (isset($epData["value"])) {
$optionItem = new NaverOptionItem("SELECT", $epData["label"]);
$optionItem->addCase(IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($epData['value'])), $epData['value']);
$naverProduct->addOptionItem($optionItem);
$combination->addOption($epData["label"], IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($epData['value'])));
}
}
$naverProduct->addCombination($combination);
}
} else if (self::isTMExtraProductOption($optionCode)) {
$itemId = intval( substr($optionCode, strlen(self::PLUGIN_TM_EXTRA_PRODUCT_OPTION)) );
$productLineItem = $refOrder->get_item($itemId);
$productLineItem->read_meta_data();
$combination = new NaverCombination($optionCode);
$tmRepo = $productLineItem->get_meta(WC_Gateway_Iamport_NaverPay::OPTION_TM_EXTRA_PRODUCT_OPTION_REPO);
if (!empty($tmRepo)) {
$tmOptionPrice = 0;
foreach($tmRepo as $tmOptionItem) {
$optionItem = new NaverOptionItem("SELECT", $tmOptionItem['name']);
$optionItem->addCase(IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($tmOptionItem['value'])), $tmOptionItem['value']);
$naverProduct->addOptionItem($optionItem);
$combination->addOption($tmOptionItem['name'], IamportNaverPayButton::sanitize_slug_for_naver(sanitize_title($tmOptionItem['value'])));