{"id":27850,"date":"2026-04-11T15:47:26","date_gmt":"2026-04-11T06:47:26","guid":{"rendered":"https:\/\/motoki-design.co.jp\/wordpress\/?p=27850"},"modified":"2026-10-23T03:09:10","modified_gmt":"2026-10-22T18:09:10","slug":"wordpress-plugin-gumroad-license-authentication","status":"publish","type":"post","link":"https:\/\/motoki-design.co.jp\/wordpress\/wordpress-plugin-gumroad-license-authentication\/","title":{"rendered":"WordPress\u2502\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u306bGumroad\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u3092\u5b9f\u88c5\u3059\u308b\u65b9\u6cd5"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">WordPress\u306e\u6709\u6599\u30d7\u30e9\u30b0\u30a4\u30f3\u3092Gumroad\u3067\u8ca9\u58f2\u3059\u308b\u5834\u5408\u3001<strong>\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c<\/strong>\u306e\u4ed5\u7d44\u307f\u3092\u3069\u3046\u4f5c\u308b\u304b\u304c\u8ab2\u984c\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u8a18\u4e8b\u3067\u306f\u3001Gumroad\u3067\u8cfc\u5165\u60c5\u5831\u3092\u691c\u8a3c\u3057\u3001\u81ea\u524d\u306eWordPress REST API\u3068MySQL\u3067\u5229\u7528\u30c9\u30e1\u30a4\u30f3\u3092\u8a18\u9332\u3059\u308b\u69cb\u6210\u3092\u6271\u3044\u307e\u3059\u3002\u63b2\u8f09\u30b3\u30fc\u30c9\u306f\u8a8d\u8a3c\u51e6\u7406\u3092\u691c\u8a0e\u3059\u308b\u305f\u3081\u306e\u53c2\u8003\u5b9f\u88c5\u3067\u3059\u3002<\/p>\n\n\n<div class=\"wp-block-group has-border -border01\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<p class=\"wp-block-paragraph\">\u30c4\u30fc\u30eb\u3092\u8ca9\u58f2\u3067\u304d\u308bGumroad\uff08\u30ac\u30e0\u30ed\u30fc\u30c9\uff09\u3067\u306f\u8cfc\u5165\u3057\u305f\u30e6\u30fc\u30b6\u30fc\u3054\u3068\u306b\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u304c\u767a\u884c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\"><strong>\u63b2\u8f09\u30b3\u30fc\u30c9\u306b\u306f\u5b9a\u671f\u518d\u8a8d\u8a3c\u306e\u5b9f\u884c\u51e6\u7406\u304c\u3042\u308a\u307e\u305b\u3093\u3002<\/strong>\u901a\u4fe1\u969c\u5bb3\u3068\u7121\u52b9\u30ad\u30fc\u306e\u533a\u5225\u3001\u540c\u6642\u767b\u9332\u6642\u306e\u4e0a\u9650\u4fdd\u8a3c\u3001\u30b5\u30a4\u30c8\u6240\u6709\u78ba\u8a8d\u306a\u3069\u3082\u5b9f\u88c5\u304c\u5fc5\u8981\u3067\u3059\u3002\u305d\u306e\u307e\u307e\u8ca9\u58f2\u7528\u306e\u8a8d\u8a3c\u57fa\u76e4\u3068\u3057\u3066\u5c0e\u5165\u305b\u305a\u3001\u4ee5\u4e0b\u306e\u5236\u7d04\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"812\" height=\"500\" alt=\"Gumroad\u3067\u8cfc\u5165\u3057\u305f\u30e6\u30fc\u30b6\u30fc\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3092\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u3067\u5b9a\u671f\u7684\u306b\u81ea\u52d5\u8a8d\u8a3c\u3059\u308b\u4ed5\u7d44\u307f\u306e\u30a4\u30e1\u30fc\u30b8\u3002\" class=\"wp-image-27853\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-812x500.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-812x500.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-382x235.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-768x473.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n<\/div><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u5225\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u7ba1\u7406\u30b5\u30fc\u30d3\u30b9\u306f\u4f7f\u3044\u307e\u305b\u3093\u304c\u3001Gumroad\u3078\u306e\u4f9d\u5b58\u3001\u8ca9\u58f2\u624b\u6570\u6599\u3001\u30b5\u30fc\u30d0\u30fc\u4ee3\u3001\u4fdd\u5b88\u4f5c\u696d\u306f\u6b8b\u308a\u307e\u3059\u3002 <a href=\"https:\/\/gumroad.com\/pricing\">Gumroad\u6599\u91d1\u6848\u5185<\/a><\/p>\n\n\n<h2 class=\"wp-block-heading\">\u3053\u306e\u8a18\u4e8b\u3067\u6271\u3046\u69cb\u6210<\/h2>\n\n\n<ul class=\"wp-block-list is-style-num_circle\">\n<li>\u8cfc\u5165\u8005\u304cGumroad\u3067\u8cfc\u5165\n<ul class=\"wp-block-list\">\n<li>  \u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u304c\u767a\u884c\u3055\u308c\u308b<\/li>\n<\/ul>\n<\/li>\n\n\n<li>\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb \u2192 \u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3092\u5165\u529b\n<ul class=\"wp-block-list\">\n<li>    WordPress REST API\u30b5\u30fc\u30d0\u30fc\u306b\u9001\u4fe1<\/li>\n<\/ul>\n<\/li>\n\n\n<li>Gumroad API\u3067\u30e9\u30a4\u30bb\u30f3\u30b9\u691c\u8a3c \uff0b MySQL\u306b\u30b5\u30a4\u30c8\u767b\u9332\n<ul class=\"wp-block-list\">\n<li>    \u901a\u5e38\u306e\u9010\u6b21\u51e6\u7406\u3067\u306f\u6700\u59273\u30c9\u30e1\u30a4\u30f3\u3092\u60f3\u5b9a\uff08\u540c\u6642\u767b\u9332\u306e\u6392\u4ed6\u5236\u5fa1\u306f\u672a\u5b9f\u88c5\uff09<\/li>\n<\/ul>\n<\/li>\n\n\n<li>\u6709\u6599\u6a5f\u80fd\u304c\u4f7f\u3048\u308b\u3088\u3046\u306b\u306a\u308b<br\/><\/li>\n<\/ul>\n\n\n<h3 class=\"wp-block-heading\"><strong>\u6280\u8853\u30b9\u30bf\u30c3\u30af<\/strong><\/h3>\n\n\n<ul class=\"wp-block-list is-style-num_circle\">\n<li>\u8ca9\u58f2\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0: Gumroad<\/li>\n\n\n<li>\u30e9\u30a4\u30bb\u30f3\u30b9\u691c\u8a3c: Gumroad License Verify API\uff08\u691c\u8a3c\u30ea\u30af\u30a8\u30b9\u30c8\u306b\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u306f\u4e0d\u8981\uff09<\/li>\n\n\n<li>\u30d0\u30c3\u30af\u30a8\u30f3\u30c9: WordPress REST API\uff08\u30b7\u30f3\u30ec\u30f3\u30bf\u30eb\u30b5\u30fc\u30d0\u30fc\uff09<\/li>\n\n\n<li>\u30c7\u30fc\u30bf\u4fdd\u5b58: MySQL\uff08WordPress\u306eDB\uff09<\/li>\n\n\n<li>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8: \u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u5074PHP<\/li>\n<\/ul>\n\n\n<p class=\"wp-block-paragraph\">\u305d\u308c\u3067\u306f\u3084\u308a\u65b9\u3092\u8a73\u3057\u304f\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">\u5c0e\u5165\u306e\u6d41\u308c<\/h2>\n\n\n<p class=\"wp-block-paragraph\">\u8cfc\u5165\u30fb\u8a8d\u8a3c\u306e\u6d41\u308c\u306f\u6b21\u306e\u3068\u304a\u308a\u3067\u3059\u3002\u8a2d\u5b9a\u753b\u9762\u3092\u542b\u3080\u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u5168\u4f53\u306f\u63b2\u8f09\u3057\u3066\u3044\u306a\u3044\u305f\u3081\u3001\u4ee5\u4e0b\u3060\u3051\u3067\u306f\u52d5\u4f5c\u3059\u308b\u88fd\u54c1\u306b\u306f\u306a\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">Gumroad\u306b\u5546\u54c1\u3092\u767b\u9332<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u5546\u54c1\u306b\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306e\u767a\u884c\u3092\u8a2d\u5b9a\u3057\u3001\u5546\u54c1\u7de8\u96c6\u753b\u9762\u306b\u8868\u793a\u3055\u308c\u308bProduct ID\u3092\u63a7\u3048\u307e\u3059\u3002\u3053\u308c\u306f\u5546\u54c1\u306e\u8b58\u5225\u5b50\u3067\u3001\u8cfc\u5165\u8005\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3084API\u306e\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u3068\u306f\u7570\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"812\" height=\"500\" alt=\"Gumroad\u3067\u306e\u5546\u54c1\u767b\u9332\u6642\u306b\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306e\u9805\u76ee\u3092\u8ffd\u52a0\u3057\u3001API\u30ad\u30fc\u3092\u78ba\u8a8d\u3059\u308b\u753b\u9762\u306e\u69d8\u5b50\u3002\" class=\"wp-image-27853\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-812x500.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-812x500.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-382x235.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18-768x473.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h14_18.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"812\" height=\"385\" alt=\"\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u306bGumroad\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u3092\u5b9f\u88c5\u3059\u308b\u624b\u9806\u306e\u30a4\u30e1\u30fc\u30b8\u3002\" class=\"wp-image-27856\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h48_31-812x385.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h48_31-812x385.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h48_31-382x181.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h48_31-768x364.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h48_31.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306e\u74b0\u5883\u69cb\u7bc9<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3\u7b49\u3067\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u7528\u306bWordPress\u30b5\u30a4\u30c8\u3092\u7acb\u3061\u4e0a\u3052\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u63b2\u8f09\u30b3\u30fc\u30c9\u3092\u4f7f\u3046\u5834\u5408\u306f\u3001\u5148\u306b\u691c\u8a3c\u7528WordPress\u3068\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u7528\u610f\u3057\u307e\u3059\u3002\u30b3\u30fc\u30c9\u306e\u4fee\u6b63\u30fb\u30c6\u30b9\u30c8\u3092\u6e08\u307e\u305b\u3066\u304b\u3089\u30d7\u30e9\u30b0\u30a4\u30f3\u3068\u3057\u3066\u7d44\u307f\u8fbc\u307f\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">WordPress\u306e\u7ba1\u7406\u753b\u9762\uff1e\u8a2d\u5b9a\uff1eLicense Server\u304b\u3089Gumroad Product ID\uff08xxxxxxxxxxxxxxxxxxx-X==\uff09\u3092\u767b\u9332\u3057\u3066\u4fdd\u5b58\u3057\u307e\u3059\u3002<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"812\" height=\"420\" alt=\"WordPress\u306e\u8a2d\u5b9a\u753b\u9762\u306b\u3042\u308b\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u9805\u76ee\u3067\u3001Gumroad\u306e\u30d7\u30ed\u30c0\u30af\u30c8ID\u3092\u767b\u9332\u3057\u3066\u4fdd\u5b58\u3059\u308b\u69d8\u5b50\u3002\" class=\"wp-image-27857\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h56_10-812x420.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h56_10-812x420.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h56_10-382x198.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h56_10-768x398.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h56_10.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n<h3 class=\"wp-block-heading\">\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8cfc\u5165<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u8ca9\u58f2\u5546\u54c1\u3068\u306f\u5206\u3051\u305f\u691c\u8a3c\u7528\u306e\u5546\u54c1\u3068\u74b0\u5883\u3067\u3001\u8cfc\u5165\u304b\u3089\u30ad\u30fc\u767a\u884c\u307e\u3067\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u30c6\u30b9\u30c8\u306e\u305f\u3081\u306b\u8ca9\u58f2\u4e2d\u306e\u5546\u54c1\u306e\u4fa1\u683c\u30920\u5186\u3078\u5909\u66f4\u3059\u308b\u624b\u9806\u306f\u907f\u3051\u3001Gumroad\u306e\u8cfc\u5165\u30c6\u30b9\u30c8\u65b9\u6cd5\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c6\u30b9\u30c8\u8cfc\u5165\u306e\u30ad\u30fc\u3067API\u691c\u8a3c\u3067\u304d\u308b\u7bc4\u56f2\u3082\u5b9f\u969b\u306e\u5fdc\u7b54\u3067\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u767a\u884c\u3055\u308c\u305f\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306f\u8a8d\u8a3c\u60c5\u5831\u3068\u3057\u3066\u6271\u3044\u3001\u516c\u958b\u8a18\u4e8b\u30fb\u5171\u6709\u30ed\u30b0\u30fb\u30bd\u30fc\u30b9\u7ba1\u7406\u3078\u8a18\u8f09\u3057\u307e\u305b\u3093\u3002<\/p>\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"812\" height=\"315\" alt=\"Gumroad\u3067\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u8cfc\u5165\u3057\u3001\u767a\u884c\u3055\u308c\u305f\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3092\u78ba\u8a8d\u30fb\u53d6\u5f97\u3059\u308b\u753b\u9762\u306e\u69d8\u5b50\u3002\" class=\"wp-image-27858\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h57_47-812x315.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h57_47-812x315.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h57_47-382x148.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h57_47-768x298.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h57_47.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n<p class=\"wp-block-paragraph\">\u8cfc\u5165\u3057\u305f\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u6709\u52b9\u5316\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u8a2d\u5b9a\u304b\u3089\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3092\u5165\u308c\u3066\u4fdd\u5b58\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u6700\u5f8c\u306b\u3053\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u6709\u52b9\u5316\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n<figure class=\"wp-block-image size-large is-style-border\"><img decoding=\"async\" width=\"812\" height=\"550\" alt=\"\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8a2d\u5b9a\u753b\u9762\u3067\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3092\u5165\u529b\u3057\u3001\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u6709\u52b9\u5316\u3059\u308b\u624b\u9806\u3092\u793a\u3059\u753b\u9762\u3002\" class=\"wp-image-27859\" src=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h59_25-812x550.png\" srcset=\"https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h59_25-812x550.png 812w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h59_25-382x259.png 382w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h59_25-768x521.png 768w, https:\/\/motoki-design.co.jp\/wordpress\/wp-content\/uploads\/2026-04-11_14h59_25.png 924w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/><\/figure>\n\n\n<p class=\"is-style-icon_info wp-block-paragraph\">\u4e0a\u9650\u306f3\u30c9\u30e1\u30a4\u30f3\u3092\u60f3\u5b9a\u3057\u3066\u3044\u307e\u3059\u3002\u540c\u4e00\u30db\u30b9\u30c8\u5185\u306e\u5225\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3084\u30dd\u30fc\u30c8\u306f\u533a\u5225\u305b\u305a\u3001www\u306e\u6709\u7121\u3082\u7d71\u5408\u3059\u308b\u5b9f\u88c5\u3067\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">PHP\u3001WordPress REST API\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6271\u3044\u3092\u7406\u89e3\u3057\u305f\u3046\u3048\u3067\u3001\u5f8c\u8ff0\u306e\u672a\u5b9f\u88c5\u90e8\u5206\u3092\u88dc\u3063\u3066\u691c\u8a3c\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<p class=\"is-style-icon_pen wp-block-paragraph\">\u30b5\u30fc\u30d0\u30fc\u3068\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u53c2\u8003\u30b3\u30fc\u30c9\u3092\u63b2\u8f09\u3057\u307e\u3059\u3002\u8cfc\u5165\u30fb\u8a8d\u8a3c\u30fb\u4e0a\u9650\u5224\u5b9a\u306e\u5b9f\u6a5f\u30c6\u30b9\u30c8\u7d50\u679c\u3092\u793a\u3059\u3082\u306e\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">Gumroad\u306e\u5546\u54c1\u8b58\u5225\u5b50\u3068\u691c\u8a3cAPI<\/h2>\n\n\n<p class=\"wp-block-paragraph\">API\u3078\u6e21\u3059\u5546\u54c1\u306e\u8b58\u5225\u5b50\u3068\u8cfc\u5165\u8005\u306e\u30ad\u30fc\u3092\u533a\u5225\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u540c\u3058\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3067\u3082\u3001\u5546\u54c1\u3068\u30ad\u30fc\u306e\u7d44\u307f\u5408\u308f\u305b\u306e\u4e0d\u4e00\u81f4\u306a\u3069\u8907\u6570\u306e\u539f\u56e0\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">Product ID\u3068\u5546\u54c1URL\u306e\u30b9\u30e9\u30c3\u30b0\u306f\u5225\u306e\u5024<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u5546\u54c1URL\u306b\u4f7f\u3046\u30b9\u30e9\u30c3\u30b0\u3068\u3001API\u306eproduct_id\u306b\u6e21\u3059\u5546\u54c1\u8b58\u5225\u5b50\u3092\u533a\u5225\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u540d\u79f0<\/th><th>\u5024\u306e\u4f8b<\/th><th>\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td><strong>Permalink<\/strong>\uff08URL\u30b9\u30e9\u30c3\u30b0\uff09<\/td><td><code>hogehoge<\/code><\/td><td>\u5546\u54c1URL\u7528\u3002product_id\u306e\u4ee3\u308f\u308a\u306b\u306f\u5165\u529b\u3057\u306a\u3044<\/td><\/tr><tr><td><strong>Product ID<\/strong>\uff08API\u7528\uff09<\/td><td><code>xxxxxxxxxxxxxxxxxxx-X==<\/code><\/td><td>verify API\u306eproduct_id\u3078\u3001\u7ba1\u7406\u753b\u9762\u306e\u5024\u3092\u7701\u7565\u305b\u305a\u6e21\u3059<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<p class=\"wp-block-paragraph\"><strong>Product ID\u306e\u5834\u6240<\/strong>: \u5546\u54c1\u7de8\u96c6\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u753b\u9762\u306b\u3042\u308b\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306e\u30d6\u30ed\u30c3\u30af\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002\u753b\u9762\u4e0a\u306e\u914d\u7f6e\u306f\u5909\u66f4\u3055\u308c\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">URL\u306e\u30b9\u30e9\u30c3\u30b0\u3092product_id\u3078\u6e21\u3057\u305f\u5834\u5408\u3084\u3001\u5225\u306e\u5546\u54c1\u306b\u767a\u884c\u3055\u308c\u305f\u30ad\u30fc\u3092\u9001\u3063\u305f\u5834\u5408\u306f\u691c\u8a3c\u306b\u5931\u6557\u3057\u307e\u3059\u3002\u30a8\u30e9\u30fc\u6587\u3060\u3051\u3067\u539f\u56e0\u3092\u6c7a\u3081\u305a\u3001\u8a2d\u5b9a\u3057\u305f\u5546\u54c1ID\u3068\u8cfc\u5165\u8a18\u9332\u3092\u7167\u5408\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">Product ID\u306f\u8868\u793a\u3055\u308c\u305f\u5024\u5168\u4f53\u3092\u30b3\u30d4\u30fc\u3057\u307e\u3059\u3002\u4f8b\u306b\u306f\u672b\u5c3e\u306e\u7b49\u53f7\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u304c\u3001\u6587\u5b57\u5217\u306e\u898b\u305f\u76ee\u3060\u3051\u3067\u6b63\u5426\u3092\u5224\u5b9a\u3057\u307e\u305b\u3093\u30022023\u5e741\u67089\u65e5\u4ee5\u964d\u306b\u4f5c\u6210\u3055\u308c\u305f\u5546\u54c1\u3067\u306f\u3001Gumroad\u516c\u5f0f\u6848\u5185\u306fproduct_permalink\u3067\u306f\u306a\u304fproduct_id\u3092\u8981\u6c42\u3057\u3066\u3044\u307e\u3059\u3002 <a href=\"https:\/\/gumroad.com\/help\/article\/76-license-keys\">Gumroad\u516c\u5f0f\uff1aLicense keys<\/a><\/p>\n\n\n<h3 class=\"wp-block-heading\">Gumroad License Verify API\u306fAPI\u30ad\u30fc\u4e0d\u8981<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u3001product_id\u3068license_key\u3060\u3051\u3067\u691c\u8a3c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>curl -X POST https:\/\/api.gumroad.com\/v2\/licenses\/verify \\\n  -d \"product_id=xxxxxxxxxxxxxxxxxxx-X==\" \\\n  -d \"license_key=XXXX-XXXX-XXXX-XXXX\" \\\n  -d \"increment_uses_count=false\"<\/code><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>increment_uses_count=false<\/code> \u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u3067Gumroad\u5074\u306e\u4f7f\u7528\u30ab\u30a6\u30f3\u30c8\u3092\u5897\u3084\u3055\u305a\u3001\u30b5\u30a4\u30c8\u6570\u7ba1\u7406\u306f\u81ea\u524d\u3067\u884c\u3044\u307e\u3059\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">Step 1: \u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u7528WordPress\u3092\u8a2d\u7f6e<\/h2>\n\n\n<h3 class=\"wp-block-heading\">\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3\u3092\u8ffd\u52a0\u3057\u3066WordPress\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u30ec\u30f3\u30bf\u30eb\u30b5\u30fc\u30d0\u30fc\u306e\u5834\u5408\u3001\u7ba1\u7406\u30d1\u30cd\u30eb\u304b\u3089 <code>api.example.com<\/code> \u306e\u3088\u3046\u306a\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3\u3092\u8ffd\u52a0\u3057\u3001WordPress\u7c21\u5358\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067WordPress\u3092\u5165\u308c\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u8a2d\u5b9a\u753b\u9762\u306b\u8868\u793a\u3055\u308c\u308b\u30e9\u30a4\u30bb\u30f3\u30b9API\u306eURL\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002\u63b2\u8f09\u30d7\u30e9\u30b0\u30a4\u30f3\u306fWordPress\u306e<code>rest_url()<\/code>\u3067URL\u3092\u751f\u6210\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u30d1\u30fc\u30de\u30ea\u30f3\u30af\u3092\u300c\u6295\u7a3f\u540d\u300d\u306b\u3059\u308b\u3053\u3068\u306fREST API\u306e\u5fc5\u9808\u6761\u4ef6\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u300c\u57fa\u672c\u300d\u306e\u5834\u5408\u306f<code>?rest_route=<\/code>\u3092\u542b\u3080URL\u306b\u306a\u308a\u307e\u3059\u3002<code>rest_no_route<\/code>\u3067\u306f\u3001URL\u30fbPOST\u30e1\u30bd\u30c3\u30c9\u30fb\u30eb\u30fc\u30c8\u767b\u9332\u30fb\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u6709\u52b9\u5316\u72b6\u614b\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002 <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/get_rest_url\/\">WordPress\u516c\u5f0f\uff1aREST URL\u751f\u6210<\/a><\/p>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u4ee5\u4e0b\u306e\u69cb\u6210\u3067\u30d7\u30e9\u30b0\u30a4\u30f3\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>\/wp-content\/plugins\/My-license-server\/\n    \u2514\u2500\u2500 My-license-server.php<\/code><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u63b2\u8f09\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8868\u793a\u540d\u306f\u300cMotoki License Server\u300d\u3067\u3059\u3002\u6709\u52b9\u5316\u51e6\u7406\u306f\u6b21\u306e3\u30c6\u30fc\u30d6\u30eb\u306e\u4f5c\u6210\u3092\u8a66\u307f\u307e\u3059\u3002\u5b9f\u969b\u306b\u4f5c\u6210\u3055\u308c\u305f\u304b\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30a8\u30e9\u30fc\u304c\u306a\u3044\u304b\u3092\u691c\u8a3c\u74b0\u5883\u3067\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8868\u306ewp_\u306f\u4f8b\u3067\u3001\u5b9f\u969b\u306e\u63a5\u982d\u8f9e\u306f\u30b5\u30a4\u30c8\u3054\u3068\u306b\u7570\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>\u30c6\u30fc\u30d6\u30eb\u540d<\/th><th>\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td><code>wp_mls_licenses<\/code><\/td><td>\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u7ba1\u7406\uff08\u30cf\u30c3\u30b7\u30e5\u5316\u3057\u3066\u4fdd\u5b58\uff09<\/td><\/tr><tr><td><code>wp_mls_activations<\/code><\/td><td>\u6709\u52b9\u5316\u30b5\u30a4\u30c8\u7ba1\u7406<\/td><\/tr><tr><td><code>wp_mls_logs<\/code><\/td><td>\u30c7\u30d0\u30c3\u30b0\u7528\u30ed\u30b0<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<p class=\"wp-block-paragraph\"><strong>\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u5074<\/strong>\u3067\u306f\u30ad\u30fc\u3092SHA-256\u306e\u30cf\u30c3\u30b7\u30e5\u3068\u3057\u3066\u8a18\u9332\u3057\u307e\u3059\u3002\u4e00\u65b9\u3001\u63b2\u8f09\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8a2d\u5b9a\u304b\u3089\u5e73\u6587\u30ad\u30fc\u3092\u8aad\u307f\u51fa\u3057\u307e\u3059\u3002\u4e21\u65b9\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3067\u5e73\u6587\u3092\u4fdd\u5b58\u3057\u306a\u3044\u8a2d\u8a08\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u30b5\u30fc\u30d0\u30fc\u5074\u306b\u306f\u30ad\u30fc\u306e\u672b\u5c3e4\u6587\u5b57\u3001\u8cfc\u5165\u8005\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3001\u8cfc\u5165ID\u306a\u3069\u3082\u8a18\u9332\u3057\u307e\u3059\u3002\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30fb\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30fb\u901a\u4fe1\u30ed\u30b0\u306e\u95b2\u89a7\u6a29\u9650\u3068\u4fdd\u5b58\u671f\u9593\u3092\u7ba1\u7406\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u672b\u5c3e4\u6587\u5b57\u306f\u4e00\u610f\u306a\u8b58\u5225\u5b50\u306b\u306f\u306a\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">Step 2: Gumroad Product ID\u3092DB\u306b\u767b\u9332<\/h2>\n\n\n<p class=\"wp-block-paragraph\">WordPress\u7ba1\u7406\u753b\u9762 \u2192 <strong>\u8a2d\u5b9a \u2192 License Server<\/strong> \u3092\u958b\u304d\u3001Gumroad Product ID\u306b <code>xxxxxxxxxxxxxxxxxxx-X==<\/code>\uff08<code>==<\/code>\u307e\u3067\u542b\u3080\uff09\u3092\u5165\u529b\u3057\u3066\u4fdd\u5b58\u3057\u307e\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u7ba1\u7406\u753b\u9762\u3067\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u306a\u3044\u5834\u5408<\/h3>\n\n\n<p class=\"wp-block-paragraph\"><code>options.php<\/code>\u3078\u306e\u4fdd\u5b58\u30ea\u30af\u30a8\u30b9\u30c8\u306eHTTP\u5fdc\u7b54\u3001\u7ba1\u7406\u8005\u6a29\u9650\u3001nonce\u3001\u8a2d\u5b9a\u767b\u9332\u3001\u30b5\u30fc\u30d0\u30fc\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002\u7279\u5b9a\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30d7\u30e9\u30b0\u30a4\u30f3\u304c\u539f\u56e0\u3068\u306f\u3001\u3053\u308c\u3060\u3051\u3067\u306f\u65ad\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u539f\u56e0\u3092\u8abf\u3079\u305a\u306bSQL\u3067\u8a2d\u5b9a\u3092\u4e0a\u66f8\u304d\u3059\u308b\u3068\u3001\u8aa4\u3063\u305f\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u5909\u66f4\u3084\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30ad\u30e3\u30c3\u30b7\u30e5\u3068\u306e\u4e0d\u6574\u5408\u306b\u3064\u306a\u304c\u308a\u307e\u3059\u3002WP-CLI\u304c\u4f7f\u3048\u308b\u74b0\u5883\u3067\u306f\u3001\u5bfe\u8c61WordPress\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3068URL\u3092\u78ba\u8a8d\u3057\u3066\u8a2d\u5b9a\u3092\u66f4\u65b0\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u4ee5\u4e0b\u306fWP-CLI\u3067\u306e\u8a2d\u5b9a\u4f8b\u3067\u3059\u3002URL\u3068Product ID\u3092\u5b9f\u969b\u306e\u5024\u3078\u7f6e\u304d\u63db\u3048\u307e\u3059\u3002\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u5074\u306eProduct ID\u3092\u5fc5\u305a\u8a2d\u5b9a\u3057\u3001\u30ea\u30af\u30a8\u30b9\u30c8\u5074\u306e\u5546\u54c1\u6307\u5b9a\u306b\u4f9d\u5b58\u3055\u305b\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-sql\" data-lang=\"SQL\"><code>wp option update mls_product_id \"YOUR_PRODUCT_ID\" --url=\"https:\/\/api.example.com\"<\/code><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u8aad\u307f\u53d6\u3063\u3066\u78ba\u8a8d\u3059\u308b\u5834\u5408\u306e\u4f8b\u3067\u3059\u3002wp_\u306f\u5b9f\u969b\u306e\u63a5\u982d\u8f9e\u3078\u7f6e\u304d\u63db\u3048\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>SELECT option_name, option_value FROM wp_options\nWHERE option_name = 'mls_product_id';<\/code><\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Step 3: \u52d5\u4f5c\u78ba\u8a8d\uff08curl\uff09<\/h2>\n\n\n<h3 class=\"wp-block-heading\">Windows\u306e\u30b3\u30de\u30f3\u30c9\u30d7\u30ed\u30f3\u30d7\u30c8\u3067\u306e\u4f8b<\/h3>\n\n\n<p class=\"wp-block-paragraph\">Windows\u306e\u30b3\u30de\u30f3\u30c9\u30d7\u30ed\u30f3\u30d7\u30c8\u306f\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5 <code>\\<\/code> \u306b\u3088\u308b\u6539\u884c\u304c\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u6b21\u306fcmd.exe\u5411\u3051\u306e\u5f15\u7528\u7b26\u3092\u4f7f\u3063\u305f\u4f8b\u3067\u3059\u3002PowerShell\u3078\u305d\u306e\u307e\u307e\u6d41\u7528\u305b\u305a\u3001JSON\u30d5\u30a1\u30a4\u30eb\u3092\u6e21\u3059\u65b9\u6cd5\u306a\u3069\u4f7f\u7528\u30b7\u30a7\u30eb\u306b\u5408\u3046\u66f8\u5f0f\u306b\u3057\u307e\u3059\u3002URL\u306f\u8a2d\u5b9a\u753b\u9762\u306b\u8868\u793a\u3055\u308c\u305f\u3082\u306e\u3078\u7f6e\u304d\u63db\u3048\u3001\u691c\u8a3c\u5c02\u7528\u306e\u30ad\u30fc\u3068\u30c9\u30e1\u30a4\u30f3\u3092\u4f7f\u3063\u3066\u304f\u3060\u3055\u3044\u3002\u5b9f\u884c\u306f\u30b5\u30a4\u30c8\u767b\u9332\u3092\u4f34\u3044\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>curl -X POST https:\/\/api.example.com\/wp-json\/mls\/v1\/license -H \"Content-Type: application\/json\" -d \"{\\\"action\\\":\\\"activate\\\",\\\"license_key\\\":\\\"XXXX-XXXX-XXXX-XXXX\\\",\\\"site_url\\\":\\\"https:\/\/test.example.com\\\",\\\"product_id\\\":\\\"xxxxxxxxxxxxxxxxxxx-X==\\\",\\\"plugin_version\\\":\\\"1.0.0\\\"}\"<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">\u671f\u5f85\u3059\u308b\u30ec\u30b9\u30dd\u30f3\u30b9<\/h3>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>{\n  \"ok\": true,\n  \"status\": \"active\",\n  \"message\": \"activated\",\n  \"site_count\": 1,\n  \"max_sites\": 3,\n  \"domain\": \"test.example.com\"\n}<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Mac \/ Linux\u306e\u5834\u5408<\/h3>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>curl -X POST https:\/\/api.example.com\/wp-json\/mls\/v1\/license \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\n    \"action\": \"activate\",\n    \"license_key\": \"XXXX-XXXX-XXXX-XXXX\",\n    \"site_url\": \"https:\/\/test.example.com\",\n    \"product_id\": \"xxxxxxxxxxxxxxxxxxx-X==\",\n    \"plugin_version\": \"1.0.0\"\n  }'\n<\/code><\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Step 4: \u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u3078\u306e\u7d44\u307f\u8fbc\u307f<\/h2>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9API\u306eURL\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u3068\u3057\u3066\u57cb\u3081\u8fbc\u3080<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u8a2d\u5b9a\u753b\u9762\u3078\u306e\u521d\u671f\u8868\u793a\u306e\u4f8b\u3067\u3059\u3002\u3053\u308c\u3060\u3051\u3067\u306f\u672a\u4fdd\u5b58\u6642\u306eAPI\u547c\u3073\u51fa\u3057\u5148\u306f\u5909\u308f\u308a\u307e\u305b\u3093\u3002\u63b2\u8f09\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e<code>amu_ai_license_get_api_url()<\/code>\u3082\u540c\u3058\u65e2\u5b9a\u5024\u3092\u4f7f\u3046\u8a2d\u8a08\u306b\u3059\u308b\u304b\u3001\u5229\u7528\u958b\u59cb\u524d\u306b\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>\/\/ \u5909\u66f4\u524d\nvalue=\"&lt;?php echo esc_attr((string) ($settings['license_api_url'] ?? '')); ?&gt;\"\n\n\/\/ \u5909\u66f4\u5f8c\uff08?: \u3067\u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\uff09\nvalue=\"&lt;?php echo esc_attr((string) (($settings['license_api_url'] ?? '')\n    ?: 'https:\/\/api.example.com\/wp-json\/mls\/v1\/license')); ?&gt;\"<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">\u6709\u6599\u6a5f\u80fd\u3092\u30e9\u30a4\u30bb\u30f3\u30b9\u3067\u30ac\u30fc\u30c9\u3059\u308b<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u8a8d\u8a3c\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306b\u6a5f\u80fd\u3092\u6b62\u3081\u308b\u306b\u306f\u3001AJAX\u30cf\u30f3\u30c9\u30e9\u306e\u5171\u901a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u95a2\u6570\u306b\u30c1\u30a7\u30c3\u30af\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>function amu_ai_validate_rewrite_request(): void\n{\n    check_ajax_referer('amu_ai_rewriter', 'nonce');\n\n    \/\/ \u30e9\u30a4\u30bb\u30f3\u30b9\u30c1\u30a7\u30c3\u30af\u3092\u8ffd\u52a0\n    if ( ! function_exists('amu_ai_license_is_recently_valid') \n         || ! amu_ai_license_is_recently_valid() ) {\n        wp_send_json_error( [\n            'message' =&gt; '\u30e9\u30a4\u30bb\u30f3\u30b9\u304c\u6709\u52b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30e9\u30a4\u30bb\u30f3\u30b9\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002'\n        ], 403 );\n    }\n\n    \/\/ \u4ee5\u4e0b\u306f\u65e2\u5b58\u306e\u30b3\u30fc\u30c9\n    $post_id = isset($_POST['postId']) ? (int) $_POST['postId'] : 0;\n    if ($post_id &lt;= 0 || ! current_user_can('edit_post', $post_id)) {\n        wp_send_json_error(['message' =&gt; 'Permission denied.'], 403);\n    }\n}\n<\/code><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u95a2\u6570\u3092\u901a\u308b\u51e6\u7406\u3060\u3051\u304c\u5bfe\u8c61\u3067\u3059\u3002\u5225\u306eAJAX\u30fbREST\u30fb\u7ba1\u7406\u753b\u9762\u30fb\u30d0\u30c3\u30c1\u51e6\u7406\u304b\u3089\u6709\u6599\u6a5f\u80fd\u3092\u547c\u3079\u308b\u5834\u5408\u306f\u3001\u5404\u5165\u53e3\u306e\u6a29\u9650\u30c1\u30a7\u30c3\u30af\u3068\u8a8d\u8a3c\u5224\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u8cfc\u5165\u8005\u304c\u5909\u66f4\u3067\u304d\u308bPHP\u30b3\u30fc\u30c9\u3060\u3051\u3067\u6539\u5909\u3092\u5b8c\u5168\u306b\u9632\u3050\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">ZIP\u3092\u30d1\u30c3\u30b1\u30fc\u30b8\u3059\u308b\u969b\u306e\u6ce8\u610f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">ZIP\u5185\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u540d\u306b\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u304c\u4f7f\u308f\u308c\u3066\u3044\u308b\u5834\u5408\u3001Linux\u5074\u306e\u5c55\u958b\u3067\u554f\u984c\u304c\u8d77\u3053\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002Windows\u3067\u4f5c\u3063\u305fZIP\u3059\u3079\u3066\u306b\u8d77\u3053\u308b\u308f\u3051\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u5148\u306b\u30a2\u30fc\u30ab\u30a4\u30d6\u5185\u306e\u30d1\u30b9\u3068\u5c55\u958b\u7d50\u679c\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u6b21\u306f\u3001\u81ea\u5206\u3067\u4f5c\u6210\u3057\u305fZIP\u306e\u533a\u5207\u308a\u6587\u5b57\u3092\u4fee\u6b63\u3059\u308b\u4f8b\u3067\u3059\u3002\u5909\u63db\u5f8c\u306b\u540c\u540d\u30d1\u30b9\u306e\u91cd\u8907\u304c\u306a\u3044\u304b\u78ba\u8a8d\u3057\u3001PHP\u30d5\u30a1\u30a4\u30eb\u3084\u30d5\u30a9\u30eb\u30c0\u30fc\u304c\u610f\u56f3\u3057\u305f\u69cb\u9020\u306b\u306a\u308b\u304b\u691c\u8a3c\u3057\u307e\u3059\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>import zipfile\n\nwith zipfile.ZipFile('original.zip') as zin, \\\n     zipfile.ZipFile('fixed.zip', 'w', zipfile.ZIP_DEFLATED) as zout:\n    for item in zin.infolist():\n        new_name = item.filename.replace('\\\\', '\/')  # \u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u3092\u4fee\u6b63\n        zout.writestr(new_name, zin.read(item.filename))<\/code><\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306e\u4ed5\u7d44\u307f<\/h2>\n\n\n<h3 class=\"wp-block-heading\">API\u4ed5\u69d8<\/h3>\n\n\n<p class=\"wp-block-paragraph\">1\u3064\u306eREST\u30eb\u30fc\u30c8\u30673\u3064\u306e\u64cd\u4f5c\u3092\u53d7\u3051\u4ed8\u3051\u3001<code>action<\/code>\u3067\u5206\u5c90\u3057\u307e\u3059\u3002\u63b2\u8f09\u4f8b\u306e\u30d1\u30b9\u306f<code>POST \/wp-json\/mls\/v1\/license<\/code>\u3067\u3059\u304c\u3001\u5b9f\u969b\u306eURL\u306fWordPress\u306e\u8a2d\u5b9a\u306b\u5f93\u3044\u307e\u3059\u3002<\/p>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>action<\/th><th>\u51e6\u7406<\/th><\/tr><\/thead><tbody><tr><td><code>activate<\/code><\/td><td>\u30e9\u30a4\u30bb\u30f3\u30b9\u691c\u8a3c\u3068\u30c9\u30e1\u30a4\u30f3\u767b\u9332\uff083\u4ef6\u4e0a\u9650\u3092\u9010\u6b21\u5224\u5b9a\uff09<\/td><\/tr><tr><td><code>validate<\/code><\/td><td>\u547c\u3073\u51fa\u3055\u308c\u305f\u6642\u70b9\u3067\u6709\u52b9\u6027\u3092\u78ba\u8a8d\u3002\u5b9a\u671f\u5b9f\u884c\u51e6\u7406\u306f\u542b\u307e\u306a\u3044<\/td><\/tr><tr><td><code>deactivate<\/code><\/td><td>\u30b5\u30a4\u30c8\u306e\u89e3\u9664\uff08\u5225\u30b5\u30a4\u30c8\u3078\u79fb\u884c\u53ef\u80fd\uff09<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u306e\u6d41\u308c<\/h3>\n\n\n<ol class=\"wp-block-list is-style-num_circle\">\n<li>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304c\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\uff0b\u30b5\u30a4\u30c8URL\u3092\u9001\u4fe1<\/li>\n\n\n<li>\u30b5\u30fc\u30d0\u30fc\u304cGumroad API\u3067\u30e9\u30a4\u30bb\u30f3\u30b9\u691c\u8a3c<\/li>\n\n\n<li>\u691c\u8a3c\u5fdc\u7b54\u306e\u8fd4\u91d1\u30fb\u7d1b\u4e89\u30fb\u30c1\u30e3\u30fc\u30b8\u30d0\u30c3\u30af\u72b6\u614b\u3092\u5224\u5b9a\uff08\u5373\u6642\u901a\u77e5\u3067\u306f\u306a\u3044\uff09<\/li>\n\n\n<li>\u6709\u52b9\u306a\u3089 <code>wp_mls_activations<\/code> \u306b\u30b5\u30a4\u30c8\u3092\u767b\u9332<\/li>\n\n\n<li>\u767b\u9332\u524d\u306e\u4ef6\u6570\u304c\u4e0a\u9650\u306a\u3089<code>limit_exceeded<\/code>\u3092\u8fd4\u3059\u3002\u540c\u6642\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u6392\u4ed6\u5236\u5fa1\u306f\u5225\u9014\u5fc5\u8981<\/li>\n<\/ol>\n\n\n<h3 class=\"wp-block-heading\">\u4fdd\u5b58\u3057\u305f\u8a8d\u8a3c\u72b6\u614b\u3068\u518d\u691c\u8a3c\u306e\u5236\u7d04<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u8a8d\u8a3c\u7d50\u679c\u3092WordPress\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3078\u4fdd\u5b58\u3057\u307e\u3059\u3002\u63b2\u8f09\u30b3\u30fc\u30c9\u306e\u52d5\u4f5c\u306f\u6b21\u306e\u3068\u304a\u308a\u3067\u3001\u300c24\u6642\u9593\u3054\u3068\u306b\u81ea\u52d5\u518d\u8a8d\u8a3c\u3059\u308b\u5b9f\u88c5\u300d\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u518d\u691c\u8a3c\u306e\u8d77\u70b9<\/strong>: \u63b2\u8f09\u3055\u308c\u3066\u3044\u308b\u306e\u306f\u7ba1\u7406\u753b\u9762\u306e\u64cd\u4f5c\u3092\u53d7\u3051\u308b\u30cf\u30f3\u30c9\u30e9\u30fc\u3067\u3059\u3002\u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u306724\u6642\u9593\u3054\u3068\u306b\u5b9f\u884c\u3059\u308b\u51e6\u7406\u306f\u672a\u63b2\u8f09\u3067\u3059\u3002<\/li>\n\n\n<li><strong>\u6709\u52b9\u6027\u306e\u5224\u5b9a<\/strong>: \u4fdd\u5b58\u72b6\u614b\u304cactive\u3067\u3001\u6700\u7d42\u78ba\u8a8d\u304b\u30897\u65e5\u4ee5\u5185\u304b\u3092\u8abf\u3079\u307e\u3059\u3002\u305f\u3060\u3057\u30ed\u30fc\u30ab\u30eb\u65e5\u6642\u306e\u4fdd\u5b58\u3068strtotime\u30fbtime\u306e\u7d44\u307f\u5408\u308f\u305b\u306b\u306f\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u306e\u305a\u308c\u304c\u3042\u308a\u3001UTC\u306e\u6574\u6570\u6642\u523b\u3078\u7d71\u4e00\u3059\u308b\u306a\u3069\u306e\u4fee\u6b63\u304c\u5fc5\u8981\u3067\u3059\u3002<\/li>\n\n\n<li><strong>\u901a\u4fe1\u969c\u5bb3<\/strong>: \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u304b\u3089\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u901a\u4fe1\u5931\u6557\u3067\u306f\u4ee5\u524d\u306e\u72b6\u614b\u3092\u4fdd\u6301\u3057\u307e\u3059\u3002\u4e00\u65b9\u3001\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u304b\u3089Gumroad\u3078\u306e\u901a\u4fe1\u5931\u6557\u306f\u7121\u52b9\u30ad\u30fc\u3068\u540c\u3058\u7d50\u679c\u306b\u306a\u308a\u3001validate\u3067\u5229\u7528\u3092\u6b62\u3081\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002\u5168\u3066\u306e\u969c\u5bb3\u30677\u65e5\u9593\u306e\u7336\u4e88\u3092\u4fdd\u8a3c\u3059\u308b\u30b3\u30fc\u30c9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/li>\n<\/ul>\n\n\n<h2 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u7ba1\u7406\uff08\u904b\u55b6\u8005\u5411\u3051\uff09<\/h2>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u306e\u5bfe\u8c61\u30ec\u30b3\u30fc\u30c9\u3092\u78ba\u8a8d\u3057\u3066\u5931\u52b9\u3055\u305b\u308b<\/h3>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>-- \u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u5f8c\u306b\u5bfe\u8c61\u3092\u8aad\u307f\u53d6\u308a\u3001\u8cfc\u5165\u8a18\u9332\u3068\u7167\u5408\u3059\u308b\u3002\u672b\u5c3e4\u6587\u5b57\u3060\u3051\u3067\u306f\u7279\u5b9a\u3057\u306a\u3044\u3002\nSELECT id, product_id, license_key_hash, license_key_last4, status\nFROM wp_mls_licenses WHERE id = 0;\n\n-- 0\u3068\u8b58\u5225\u5b50\u3092\u3001\u78ba\u8a8d\u3057\u305f\u5bfe\u8c61\u306e\u5024\u3078\u7f6e\u304d\u63db\u3048\u308b\u30020\u306e\u307e\u307e\u3067\u306f\u5bfe\u8c61\u306a\u3057\u3002\nUPDATE wp_mls_licenses SET status = 'revoked'\nWHERE id = 0 AND product_id = 'CONFIRMED_PRODUCT_ID'\n  AND license_key_hash = 'CONFIRMED_SHA256';<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">\u7279\u5b9a\u30e9\u30a4\u30bb\u30f3\u30b9\u306e\u30b5\u30a4\u30c8\u767b\u9332\u3092\u89e3\u9664\u3059\u308b<\/h3>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>-- wp_\u306f\u5b9f\u969b\u306e\u63a5\u982d\u8f9e\u3078\u5909\u66f4\u3002\u8cfc\u5165\u8a18\u9332\u30fb\u30ad\u30fc\u306e\u30cf\u30c3\u30b7\u30e5\u30fb\u30c9\u30e1\u30a4\u30f3\u3092\u7167\u5408\u3059\u308b\u3002\nSELECT id, license_key_hash, domain, status\nFROM wp_mls_activations WHERE id = 0;\n\n-- 0\u3068\u8b58\u5225\u5b50\u3092\u3001\u78ba\u8a8d\u3057\u305f1\u4ef6\u306e\u5024\u3078\u7f6e\u304d\u63db\u3048\u308b\u3002\nUPDATE wp_mls_activations\nSET status = 'inactive', deactivated_at = NOW()\nWHERE id = 0 AND license_key_hash = 'CONFIRMED_SHA256'\n  AND domain = 'confirmed.example.com';<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">\u8fd4\u91d1\u5bfe\u5fdc\u306b\u3064\u3044\u3066<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u30b5\u30fc\u30d0\u30fc\u304cGumroad\u3078\u7167\u4f1a\u3057\u305f\u6642\u70b9\u3067\u3001\u8fd4\u91d1\u306a\u3069\u306e\u30d5\u30e9\u30b0\u3092\u5224\u5b9a\u3057\u307e\u3059\u3002\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u4fdd\u5b58\u72b6\u614b\u306b\u306f\u76f4\u3061\u306b\u53cd\u6620\u3055\u308c\u305a\u3001\u63b2\u8f09\u30b3\u30fc\u30c9\u306b\u306fWebhook\u53d7\u4fe1\u51e6\u7406\u3082\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u5b9a\u671f\u518d\u691c\u8a3c\u3001\u901a\u4fe1\u969c\u5bb3\u6642\u306e\u6271\u3044\u3001\u5931\u52b9\u5f8c\u306e\u89e3\u9664\u64cd\u4f5c\u3084\u554f\u3044\u5408\u308f\u305b\u5bfe\u5fdc\u3092\u8a2d\u8a08\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3\u306e\u7d42\u4e86\u65e5\u6642\u3092\u5224\u5b9a\u3059\u308b\u51e6\u7406\u3082\u63b2\u8f09\u30b3\u30fc\u30c9\u306b\u306f\u542b\u307e\u308c\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u8fd4\u91d1\u6761\u4ef6\u306f\u8ca9\u58f2\u5185\u5bb9\u3068Gumroad\u306e\u898f\u7d04\u3092\u78ba\u8a8d\u3057\u3066\u6848\u5185\u3057\u307e\u3059\u3002\u30c7\u30b8\u30bf\u30eb\u5546\u54c1\u3067\u3042\u308b\u3053\u3068\u3060\u3051\u3092\u7406\u7531\u306b\u3001\u4e00\u5f8b\u306e\u8fd4\u91d1\u4e0d\u53ef\u3092\u63a8\u5968\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u300cNo refunds\u300d\u3092\u8a2d\u5b9a\u3057\u3066\u3044\u3066\u3082Gumroad\u5074\u3067\u8fd4\u91d1\u3055\u308c\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002\u8a2d\u5b9a\u3060\u3051\u3067\u8fd4\u91d1\u3092\u9632\u3050\u524d\u63d0\u306e\u8a8d\u8a3c\u8a2d\u8a08\u306b\u306f\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044\u3002 <a href=\"https:\/\/gumroad.com\/help\/article\/51-what-is-gumroads-refund-policy\">Gumroad\u516c\u5f0f\uff1a\u8fd4\u91d1\u30dd\u30ea\u30b7\u30fc<\/a><\/p>\n\n\n<h2 class=\"wp-block-heading\">\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/h2>\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>\u30a8\u30e9\u30fc<\/th><th>\u539f\u56e0<\/th><th>\u5bfe\u51e6<\/th><\/tr><\/thead><tbody><tr><td><code>rest_no_route<\/code><\/td><td>URL\u30fb\u30e1\u30bd\u30c3\u30c9\u30fb\u30eb\u30fc\u30c8\u767b\u9332\u30fb\u6709\u52b9\u5316\u72b6\u614b\u306a\u3069\u306e\u4e0d\u4e00\u81f4<\/td><td>\u8a2d\u5b9a\u753b\u9762\u306eAPI URL\u3068POST\u3067\u78ba\u8a8d\u3002\u300c\u6295\u7a3f\u540d\u300d\u306f\u5fc5\u9808\u3067\u306f\u306a\u3044<\/td><\/tr><tr><td><code>That license does not exist for the provided product.<\/code><\/td><td>\u5546\u54c1ID\u3068\u30ad\u30fc\u306e\u7d44\u307f\u5408\u308f\u305b\u304c\u4e00\u81f4\u3057\u306a\u3044\u306a\u3069<\/td><td>\u5546\u54c1\u7de8\u96c6\u753b\u9762\u306eProduct ID\u3068\u8cfc\u5165\u8a18\u9332\u3092\u7167\u5408<\/td><\/tr><tr><td><code>License API response was invalid.<\/code><\/td><td>JSON\u3067\u306a\u3044\u5fdc\u7b54\u3001HTTP\u30a8\u30e9\u30fc\u3001\u30d7\u30ed\u30ad\u30b7\u30fbWAF\u306a\u3069<\/td><td>HTTP\u72b6\u614b\u3068\u5fdc\u7b54\u5f62\u5f0f\u3092\u78ba\u8a8d\u3002\u30ad\u30fc\u3092\u542b\u3080\u8a73\u7d30\u30ed\u30b0\u306f\u5171\u6709\u3057\u306a\u3044<\/td><\/tr><tr><td>\u7ba1\u7406\u753b\u9762\u306e\u8a2d\u5b9a\u304c\u4fdd\u5b58\u3055\u308c\u306a\u3044<\/td><td>\u6a29\u9650\u30fbnonce\u30fb\u8a2d\u5b9a\u767b\u9332\u30fbWAF\u7b49\u3092\u5207\u308a\u5206\u3051\u308b\u5fc5\u8981\u304c\u3042\u308b<\/td><td>\u4fdd\u5b58\u30ea\u30af\u30a8\u30b9\u30c8\u3068\u30ed\u30b0\u3092\u78ba\u8a8d\u3002\u539f\u56e0\u4e0d\u660e\u306e\u307e\u307eSQL\u3067\u4e0a\u66f8\u304d\u3057\u306a\u3044<\/td><\/tr><tr><td>ZIP\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u5f8c\u306b\u30a8\u30e9\u30fc<\/td><td>ZIP\u69cb\u9020\u3001\u5fc5\u8981\u30d5\u30a1\u30a4\u30eb\u3001PHP\u4e92\u63db\u6027\u306a\u3069<\/td><td>\u30a8\u30e9\u30fc\u3068ZIP\u5185\u30d1\u30b9\u3092\u78ba\u8a8d\u3057\u3001\u8a72\u5f53\u539f\u56e0\u3060\u3051\u4fee\u6b63<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<h2 class=\"wp-block-heading\">\u53c2\u8003\u30b3\u30fc\u30c9\u3068\u5c0e\u5165\u524d\u306b\u5fc5\u8981\u306a\u4fee\u6b63<\/h2>\n\n\n<p class=\"wp-block-paragraph\"><strong>\u3053\u306e\u30b3\u30fc\u30c9\u306f\u672c\u756a\u904b\u7528\u3092\u4fdd\u8a3c\u3059\u308b\u5b8c\u6210\u7248\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/strong>\u30b5\u30fc\u30d0\u30fc\u306eProduct ID\u304c\u7a7a\u306e\u3068\u304d\u30ea\u30af\u30a8\u30b9\u30c8\u5074\u306e\u5024\u3092\u63a1\u7528\u3059\u308b\u8a2d\u8a08\u306f\u3001\u8a2d\u5b9a\u4e0d\u5099\u6642\u306b\u5225\u5546\u54c1\u3092\u53d7\u3051\u4ed8\u3051\u308b\u539f\u56e0\u306b\u306a\u308a\u307e\u3059\u3002\u30b5\u30fc\u30d0\u30fc\u8a2d\u5b9a\u3092\u5fc5\u9808\u3068\u3057\u3001\u4e0d\u5099\u304c\u3042\u308c\u3070\u62d2\u5426\u3059\u308b\u5b9f\u88c5\u304c\u5fc5\u8981\u3067\u3059\u3002\u914d\u5217\u306a\u3069\u4e0d\u6b63\u306a\u578b\u306e\u5165\u529b\u3001URL\u5f62\u5f0f\u30fb\u9577\u3055\u3001API\u306e\u547c\u3073\u51fa\u3057\u983b\u5ea6\u3082\u5236\u9650\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">3\u4ef6\u4e0a\u9650\u306b\u306f\u30e9\u30a4\u30bb\u30f3\u30b9\u5358\u4f4d\u306e\u30ed\u30c3\u30af\u306a\u3069\u306e\u6392\u4ed6\u5236\u5fa1\u3068DB\u30a8\u30e9\u30fc\u51e6\u7406\u304c\u5fc5\u8981\u3067\u3059\u3002site_url\u306f\u81ea\u5df1\u7533\u544a\u3067\u6240\u6709\u78ba\u8a8d\u3092\u3057\u3066\u3044\u307e\u305b\u3093\u3002\u3055\u3089\u306b\u5b9a\u671f\u5b9f\u884c\u3001\u901a\u4fe1\u30a8\u30e9\u30fc\u3068\u7121\u52b9\u30ad\u30fc\u306e\u533a\u5225\u3001UTC\u6642\u523b\u3078\u306e\u7d71\u4e00\u3001\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3\u72b6\u614b\u306e\u5224\u5b9a\u3001\u6210\u529f\u30fb\u5931\u6557\u901a\u77e5\u306e\u51fa\u3057\u5206\u3051\u3092\u5b9f\u88c5\u3057\u3066\u30c6\u30b9\u30c8\u3057\u307e\u3059\u3002\u6b21\u306e\u30b5\u30fc\u30d0\u30fc\u30fb\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u672c\u4f53\u306f\u3001\u3053\u308c\u3089\u304c\u672a\u5bfe\u5fdc\u306e\u53c2\u8003\u30b3\u30fc\u30c9\u3068\u3057\u3066\u63b2\u8f09\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u7528\u30d7\u30e9\u30b0\u30a4\u30f3<\/h3>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>&lt;?php\n\/**\n * Plugin Name: Motoki License Server\n * Description: Gumroad\u9023\u643aWordPress\u6709\u6599\u30d7\u30e9\u30b0\u30a4\u30f3\u7528\u30e9\u30a4\u30bb\u30f3\u30b9\u7ba1\u7406\u30b5\u30fc\u30d0\u30fc\n * Version: 1.0.0\n * Author: MOTOKI\u5408\u540c\u4f1a\u793e\n *\/\n\ndefined( 'ABSPATH' ) || exit;\n\ndefine( 'MLS_VERSION', '1.0.0' );\ndefine( 'MLS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u6709\u52b9\u5316\u6642: \u30c6\u30fc\u30d6\u30eb\u4f5c\u6210\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nregister_activation_hook( __FILE__, 'mls_activate' );\nfunction mls_activate() {\n    mls_create_tables();\n}\n\nfunction mls_create_tables() {\n    global $wpdb;\n    $charset = $wpdb-&gt;get_charset_collate();\n\n    \/\/ licenses \u30c6\u30fc\u30d6\u30eb\n    $sql_licenses = \"CREATE TABLE IF NOT EXISTS {$wpdb-&gt;prefix}mls_licenses (\n        id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n        license_key_hash VARCHAR(64)  NOT NULL,\n        license_key_last4 CHAR(4)     NOT NULL,\n        product_id      VARCHAR(100)  NOT NULL,\n        status          ENUM('active','revoked','invalid') NOT NULL DEFAULT 'active',\n        max_sites       TINYINT UNSIGNED NOT NULL DEFAULT 3,\n        gumroad_email   VARCHAR(255)  NOT NULL DEFAULT '',\n        gumroad_purchase_id VARCHAR(100) NOT NULL DEFAULT '',\n        created_at      DATETIME      NOT NULL,\n        updated_at      DATETIME      NOT NULL,\n        last_verified_at DATETIME     NULL,\n        PRIMARY KEY (id),\n        UNIQUE KEY uq_hash_product (license_key_hash, product_id),\n        KEY idx_hash (license_key_hash)\n    ) $charset;\";\n\n    \/\/ activations \u30c6\u30fc\u30d6\u30eb\n    $sql_activations = \"CREATE TABLE IF NOT EXISTS {$wpdb-&gt;prefix}mls_activations (\n        id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n        license_key_hash VARCHAR(64)  NOT NULL,\n        site_hash       VARCHAR(64)   NOT NULL,\n        domain          VARCHAR(255)  NOT NULL,\n        normalized_site VARCHAR(255)  NOT NULL,\n        status          ENUM('active','inactive') NOT NULL DEFAULT 'active',\n        activated_at    DATETIME      NOT NULL,\n        deactivated_at  DATETIME      NULL,\n        last_seen_at    DATETIME      NOT NULL,\n        PRIMARY KEY (id),\n        UNIQUE KEY uq_license_site (license_key_hash, site_hash),\n        KEY idx_license (license_key_hash)\n    ) $charset;\";\n\n    \/\/ logs \u30c6\u30fc\u30d6\u30eb\n    $sql_logs = \"CREATE TABLE IF NOT EXISTS {$wpdb-&gt;prefix}mls_logs (\n        id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n        timestamp       DATETIME      NOT NULL,\n        action          VARCHAR(20)   NOT NULL,\n        license_key_last4 CHAR(4)    NOT NULL DEFAULT '',\n        domain          VARCHAR(255)  NOT NULL DEFAULT '',\n        result          VARCHAR(20)   NOT NULL,\n        message         TEXT          NOT NULL,\n        PRIMARY KEY (id),\n        KEY idx_timestamp (timestamp)\n    ) $charset;\";\n\n    require_once ABSPATH . 'wp-admin\/includes\/upgrade.php';\n    dbDelta( $sql_licenses );\n    dbDelta( $sql_activations );\n    dbDelta( $sql_logs );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ REST API \u767b\u9332\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nadd_action( 'rest_api_init', 'mls_register_routes' );\nfunction mls_register_routes() {\n    register_rest_route( 'mls\/v1', '\/license', [\n        'methods'             =&gt; 'POST',\n        'callback'            =&gt; 'mls_handle_request',\n        'permission_callback' =&gt; '__return_true', \/\/ \u8a8d\u8a3c\u306f\u30a2\u30d7\u30ea\u5074\u3067\u884c\u3046\n    ] );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u30e1\u30a4\u30f3\u30cf\u30f3\u30c9\u30e9\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction mls_handle_request( WP_REST_Request $request ) {\n    $body = $request-&gt;get_json_params();\n    if ( empty( $body ) ) {\n        \/\/ form-urlencoded \u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af\n        $body = $request-&gt;get_params();\n    }\n\n    $action = sanitize_text_field( $body['action'] ?? '' );\n\n    switch ( $action ) {\n        case 'activate':\n            return mls_action_activate( $body );\n        case 'validate':\n            return mls_action_validate( $body );\n        case 'deactivate':\n            return mls_action_deactivate( $body );\n        default:\n            return mls_json_error( 'invalid_action', '\u4e0d\u6b63\u306a\u30a2\u30af\u30b7\u30e7\u30f3\u3067\u3059', 400 );\n    }\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ activate\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction mls_action_activate( array $body ) {\n    \/\/ \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n    $v = mls_validate_input( $body, [ 'license_key', 'site_url' ] );\n    if ( is_wp_error( $v ) ) {\n        return mls_json_error( 'validation_error', $v-&gt;get_error_message(), 400 );\n    }\n\n    $license_key = $body['license_key'];\n    $product_id  = mls_get_product_id( $body );\n    $site_url    = $body['site_url'];\n\n    $normalized  = mls_normalize_site_url( $site_url );\n    $key_hash    = mls_sha256( $license_key );\n    $site_hash   = mls_sha256( $normalized );\n    $key_last4   = substr( $license_key, -4 );\n\n    \/\/ Gumroad verify\n    $gumroad = mls_verify_gumroad( $license_key, $product_id );\n    if ( ! $gumroad['valid'] ) {\n        mls_write_log( 'activate', $key_last4, $normalized, 'fail', 'Gumroad invalid: ' . $gumroad['reason'] );\n        return mls_json_error( 'license_invalid', '\u30e9\u30a4\u30bb\u30f3\u30b9\u304c\u7121\u52b9\u3067\u3059', 403 );\n    }\n\n    global $wpdb;\n    $now = current_time( 'mysql' );\n\n    \/\/ licenses upsert\n    $license = mls_find_license( $key_hash, $product_id );\n    if ( ! $license ) {\n        $wpdb-&gt;insert( $wpdb-&gt;prefix . 'mls_licenses', [\n            'license_key_hash'    =&gt; $key_hash,\n            'license_key_last4'   =&gt; $key_last4,\n            'product_id'          =&gt; $product_id,\n            'status'              =&gt; 'active',\n            'max_sites'           =&gt; 3,\n            'gumroad_email'       =&gt; $gumroad['email'],\n            'gumroad_purchase_id' =&gt; $gumroad['purchase_id'],\n            'created_at'          =&gt; $now,\n            'updated_at'          =&gt; $now,\n            'last_verified_at'    =&gt; $now,\n        ] );\n        $license = mls_find_license( $key_hash, $product_id );\n    } else {\n        \/\/ revoked \u30c1\u30a7\u30c3\u30af\n        if ( $license-&gt;status === 'revoked' ) {\n            mls_write_log( 'activate', $key_last4, $normalized, 'fail', 'License revoked' );\n            return mls_json_error( 'license_revoked', '\u3053\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u306f\u7121\u52b9\u5316\u3055\u308c\u3066\u3044\u307e\u3059', 403 );\n        }\n        \/\/ last_verified_at \u66f4\u65b0\n        $wpdb-&gt;update(\n            $wpdb-&gt;prefix . 'mls_licenses',\n            [ 'last_verified_at' =&gt; $now, 'updated_at' =&gt; $now, 'gumroad_email' =&gt; $gumroad['email'] ],\n            [ 'id' =&gt; $license-&gt;id ]\n        );\n    }\n\n    $max_sites = (int) $license-&gt;max_sites;\n\n    \/\/ \u540c\u4e00\u30b5\u30a4\u30c8\u304c\u65e2\u306b\u30a2\u30af\u30c6\u30a3\u30d6 \u2192 \u51aa\u7b49\u6210\u529f\n    $existing = mls_find_active_activation( $key_hash, $site_hash );\n    if ( $existing ) {\n        $wpdb-&gt;update(\n            $wpdb-&gt;prefix . 'mls_activations',\n            [ 'last_seen_at' =&gt; $now ],\n            [ 'id' =&gt; $existing-&gt;id ]\n        );\n        $count = mls_count_active_activations( $key_hash );\n        mls_write_log( 'activate', $key_last4, $normalized, 'ok', 'Already active (idempotent)' );\n        return rest_ensure_response( [\n            'ok'        =&gt; true,\n            'status'    =&gt; 'active',\n            'message'   =&gt; 'already_active',\n            'site_count' =&gt; $count,\n            'max_sites' =&gt; $max_sites,\n            'domain'    =&gt; $normalized,\n        ] );\n    }\n\n    \/\/ \u4f7f\u7528\u6570\u30c1\u30a7\u30c3\u30af\n    $count = mls_count_active_activations( $key_hash );\n    if ( $count &gt;= $max_sites ) {\n        mls_write_log( 'activate', $key_last4, $normalized, 'fail', \"Limit exceeded: {$count}\/{$max_sites}\" );\n        return rest_ensure_response( [\n            'ok'        =&gt; false,\n            'status'    =&gt; 'limit_exceeded',\n            'message'   =&gt; '\u6709\u52b9\u5316\u3067\u304d\u308b\u30b5\u30a4\u30c8\u6570\u306e\u4e0a\u9650\u306b\u9054\u3057\u3066\u3044\u307e\u3059',\n            'site_count' =&gt; $count,\n            'max_sites' =&gt; $max_sites,\n        ] );\n    }\n\n    \/\/ activation \u4f5c\u6210\uff08UPSERT: inactive\u884c\u304c\u3042\u308c\u3070\u518dactive\u5316\uff09\n    $row = $wpdb-&gt;get_row( $wpdb-&gt;prepare(\n        \"SELECT * FROM {$wpdb-&gt;prefix}mls_activations WHERE license_key_hash=%s AND site_hash=%s\",\n        $key_hash, $site_hash\n    ) );\n\n    if ( $row ) {\n        $wpdb-&gt;update(\n            $wpdb-&gt;prefix . 'mls_activations',\n            [ 'status' =&gt; 'active', 'activated_at' =&gt; $now, 'deactivated_at' =&gt; null, 'last_seen_at' =&gt; $now, 'domain' =&gt; $normalized ],\n            [ 'id' =&gt; $row-&gt;id ]\n        );\n    } else {\n        $wpdb-&gt;insert( $wpdb-&gt;prefix . 'mls_activations', [\n            'license_key_hash' =&gt; $key_hash,\n            'site_hash'        =&gt; $site_hash,\n            'domain'           =&gt; $normalized,\n            'normalized_site'  =&gt; $normalized,\n            'status'           =&gt; 'active',\n            'activated_at'     =&gt; $now,\n            'deactivated_at'   =&gt; null,\n            'last_seen_at'     =&gt; $now,\n        ] );\n    }\n\n    $count = mls_count_active_activations( $key_hash );\n    mls_write_log( 'activate', $key_last4, $normalized, 'ok', \"Activated. {$count}\/{$max_sites}\" );\n\n    return rest_ensure_response( [\n        'ok'        =&gt; true,\n        'status'    =&gt; 'active',\n        'message'   =&gt; 'activated',\n        'site_count' =&gt; $count,\n        'max_sites' =&gt; $max_sites,\n        'domain'    =&gt; $normalized,\n    ] );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ validate\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction mls_action_validate( array $body ) {\n    $v = mls_validate_input( $body, [ 'license_key', 'site_url' ] );\n    if ( is_wp_error( $v ) ) {\n        return mls_json_error( 'validation_error', $v-&gt;get_error_message(), 400 );\n    }\n\n    $license_key = $body['license_key'];\n    $product_id  = mls_get_product_id( $body );\n    $site_url    = $body['site_url'];\n\n    $normalized = mls_normalize_site_url( $site_url );\n    $key_hash   = mls_sha256( $license_key );\n    $site_hash  = mls_sha256( $normalized );\n    $key_last4  = substr( $license_key, -4 );\n\n    \/\/ Gumroad verify\n    $gumroad = mls_verify_gumroad( $license_key, $product_id );\n    if ( ! $gumroad['valid'] ) {\n        mls_write_log( 'validate', $key_last4, $normalized, 'fail', 'Gumroad invalid: ' . $gumroad['reason'] );\n        return rest_ensure_response( [\n            'ok'     =&gt; true,\n            'valid'  =&gt; false,\n            'status' =&gt; 'license_invalid',\n        ] );\n    }\n\n    \/\/ \u30e9\u30a4\u30bb\u30f3\u30b9\u884c\u30c1\u30a7\u30c3\u30af\n    $license = mls_find_license( $key_hash, $product_id );\n    if ( ! $license || $license-&gt;status === 'revoked' ) {\n        mls_write_log( 'validate', $key_last4, $normalized, 'fail', 'License not found or revoked' );\n        return rest_ensure_response( [\n            'ok'     =&gt; true,\n            'valid'  =&gt; false,\n            'status' =&gt; 'license_revoked',\n        ] );\n    }\n\n    $max_sites = (int) $license-&gt;max_sites;\n    $count     = mls_count_active_activations( $key_hash );\n\n    \/\/ last_verified_at \u66f4\u65b0\n    global $wpdb;\n    $now = current_time( 'mysql' );\n    $wpdb-&gt;update(\n        $wpdb-&gt;prefix . 'mls_licenses',\n        [ 'last_verified_at' =&gt; $now, 'updated_at' =&gt; $now ],\n        [ 'id' =&gt; $license-&gt;id ]\n    );\n\n    \/\/ activation \u30c1\u30a7\u30c3\u30af\n    $activation = mls_find_active_activation( $key_hash, $site_hash );\n    if ( $activation ) {\n        $wpdb-&gt;update(\n            $wpdb-&gt;prefix . 'mls_activations',\n            [ 'last_seen_at' =&gt; $now ],\n            [ 'id' =&gt; $activation-&gt;id ]\n        );\n        mls_write_log( 'validate', $key_last4, $normalized, 'ok', 'Valid' );\n        return rest_ensure_response( [\n            'ok'        =&gt; true,\n            'valid'     =&gt; true,\n            'status'    =&gt; 'active',\n            'site_count' =&gt; $count,\n            'max_sites' =&gt; $max_sites,\n            'domain'    =&gt; $normalized,\n        ] );\n    }\n\n    mls_write_log( 'validate', $key_last4, $normalized, 'fail', 'Not activated for this site' );\n    return rest_ensure_response( [\n        'ok'        =&gt; true,\n        'valid'     =&gt; false,\n        'status'    =&gt; 'not_activated_for_this_site',\n        'site_count' =&gt; $count,\n        'max_sites' =&gt; $max_sites,\n    ] );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ deactivate\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction mls_action_deactivate( array $body ) {\n    $v = mls_validate_input( $body, [ 'license_key', 'site_url' ] );\n    if ( is_wp_error( $v ) ) {\n        return mls_json_error( 'validation_error', $v-&gt;get_error_message(), 400 );\n    }\n\n    $license_key = $body['license_key'];\n    $product_id  = mls_get_product_id( $body );\n    $site_url    = $body['site_url'];\n\n    $normalized = mls_normalize_site_url( $site_url );\n    $key_hash   = mls_sha256( $license_key );\n    $site_hash  = mls_sha256( $normalized );\n    $key_last4  = substr( $license_key, -4 );\n\n    \/\/ Gumroad verify\uff08\u89e3\u9664\u6642\u3082\u78ba\u8a8d\uff09\n    $gumroad = mls_verify_gumroad( $license_key, $product_id );\n    if ( ! $gumroad['valid'] ) {\n        mls_write_log( 'deactivate', $key_last4, $normalized, 'fail', 'Gumroad invalid' );\n        return mls_json_error( 'license_invalid', '\u30e9\u30a4\u30bb\u30f3\u30b9\u304c\u7121\u52b9\u3067\u3059', 403 );\n    }\n\n    global $wpdb;\n    $now = current_time( 'mysql' );\n\n    $activation = mls_find_active_activation( $key_hash, $site_hash );\n    if ( $activation ) {\n        $wpdb-&gt;update(\n            $wpdb-&gt;prefix . 'mls_activations',\n            [ 'status' =&gt; 'inactive', 'deactivated_at' =&gt; $now ],\n            [ 'id' =&gt; $activation-&gt;id ]\n        );\n    }\n\n    $count = mls_count_active_activations( $key_hash );\n    $license = mls_find_license( $key_hash, $product_id );\n    $max_sites = $license ? (int) $license-&gt;max_sites : 3;\n\n    mls_write_log( 'deactivate', $key_last4, $normalized, 'ok', \"Deactivated. remaining: {$count}\/{$max_sites}\" );\n\n    return rest_ensure_response( [\n        'ok'        =&gt; true,\n        'status'    =&gt; 'deactivated',\n        'site_count' =&gt; $count,\n        'max_sites' =&gt; $max_sites,\n    ] );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ Gumroad verify\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction mls_verify_gumroad( string $license_key, string $product_id ): array {\n    \/\/ Gumroad verify API\u306b product_id\uff08Base64\u5f62\u5f0f\uff09\u3092\u9001\u308b\u3002API\u30ad\u30fc\u4e0d\u8981\u3002\n    $response = wp_remote_post( 'https:\/\/api.gumroad.com\/v2\/licenses\/verify', [\n        'timeout' =&gt; 10,\n        'body'    =&gt; [\n            'product_id'           =&gt; $product_id,\n            'license_key'          =&gt; $license_key,\n            'increment_uses_count' =&gt; 'false',\n        ],\n    ] );\n\n    if ( is_wp_error( $response ) ) {\n        return [ 'valid' =&gt; false, 'reason' =&gt; 'network_error', 'email' =&gt; '', 'purchase_id' =&gt; '' ];\n    }\n\n    $code = wp_remote_retrieve_response_code( $response );\n    $data = json_decode( wp_remote_retrieve_body( $response ), true );\n\n    if ( $code !== 200 || empty( $data['success'] ) ) {\n        $reason = $data['message'] ?? 'invalid';\n        return [ 'valid' =&gt; false, 'reason' =&gt; $reason, 'email' =&gt; '', 'purchase_id' =&gt; '' ];\n    }\n\n    $purchase = $data['purchase'] ?? [];\n\n    \/\/ \u8fd4\u91d1\u30fb\u7d1b\u4e89\u30c1\u30a7\u30c3\u30af\n    if ( ! empty( $purchase['refunded'] ) || ! empty( $purchase['disputed'] ) || ! empty( $purchase['chargebacked'] ) ) {\n        return [ 'valid' =&gt; false, 'reason' =&gt; 'refunded_or_disputed', 'email' =&gt; '', 'purchase_id' =&gt; '' ];\n    }\n\n    return [\n        'valid'       =&gt; true,\n        'reason'      =&gt; '',\n        'email'       =&gt; sanitize_email( $purchase['email'] ?? '' ),\n        'purchase_id' =&gt; sanitize_text_field( $purchase['id'] ?? $purchase['sale_id'] ?? '' ),\n    ];\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\u95a2\u6570\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/** site_url \u3092\u6b63\u898f\u5316\u3059\u308b *\/\nfunction mls_normalize_site_url( string $url ): string {\n    $url = strtolower( trim( $url ) );\n    \/\/ scheme\u304c\u306a\u3051\u308c\u3070\u4ed8\u52a0\u3057\u3066parse_url\u3092\u901a\u3059\n    if ( ! preg_match( '#^https?:\/\/#', $url ) ) {\n        $url = 'https:\/\/' . $url;\n    }\n    $parsed = parse_url( $url );\n    $host   = $parsed['host'] ?? $url;\n    \/\/ www. \u9664\u53bb\n    $host   = preg_replace( '\/^www\\.\/', '', $host );\n    return $host;\n}\n\n\/** SHA-256\u30cf\u30c3\u30b7\u30e5 *\/\nfunction mls_sha256( string $value ): string {\n    return hash( 'sha256', $value );\n}\n\n\/** \u30e9\u30a4\u30bb\u30f3\u30b9\u884c\u53d6\u5f97 *\/\nfunction mls_find_license( string $key_hash, string $product_id ) {\n    global $wpdb;\n    return $wpdb-&gt;get_row( $wpdb-&gt;prepare(\n        \"SELECT * FROM {$wpdb-&gt;prefix}mls_licenses WHERE license_key_hash=%s AND product_id=%s LIMIT 1\",\n        $key_hash, $product_id\n    ) );\n}\n\n\/** \u30a2\u30af\u30c6\u30a3\u30d6\u306aactivation\u884c\u53d6\u5f97 *\/\nfunction mls_find_active_activation( string $key_hash, string $site_hash ) {\n    global $wpdb;\n    return $wpdb-&gt;get_row( $wpdb-&gt;prepare(\n        \"SELECT * FROM {$wpdb-&gt;prefix}mls_activations WHERE license_key_hash=%s AND site_hash=%s AND status='active' LIMIT 1\",\n        $key_hash, $site_hash\n    ) );\n}\n\n\/** \u30a2\u30af\u30c6\u30a3\u30d6\u306aactivation\u6570 *\/\nfunction mls_count_active_activations( string $key_hash ): int {\n    global $wpdb;\n    return (int) $wpdb-&gt;get_var( $wpdb-&gt;prepare(\n        \"SELECT COUNT(*) FROM {$wpdb-&gt;prefix}mls_activations WHERE license_key_hash=%s AND status='active'\",\n        $key_hash\n    ) );\n}\n\n\/** \u30ed\u30b0\u66f8\u304d\u8fbc\u307f *\/\nfunction mls_write_log( string $action, string $key_last4, string $domain, string $result, string $message ) {\n    global $wpdb;\n    $wpdb-&gt;insert( $wpdb-&gt;prefix . 'mls_logs', [\n        'timestamp'         =&gt; current_time( 'mysql' ),\n        'action'            =&gt; $action,\n        'license_key_last4' =&gt; $key_last4,\n        'domain'            =&gt; $domain,\n        'result'            =&gt; $result,\n        'message'           =&gt; $message,\n    ] );\n\n    \/\/ \u30ed\u30b0\u304c10000\u884c\u3092\u8d85\u3048\u305f\u3089\u53e4\u3044\u884c\u3092\u524a\u9664\n    $count = (int) $wpdb-&gt;get_var( \"SELECT COUNT(*) FROM {$wpdb-&gt;prefix}mls_logs\" );\n    if ( $count &gt; 10000 ) {\n        $wpdb-&gt;query( \"DELETE FROM {$wpdb-&gt;prefix}mls_logs ORDER BY id ASC LIMIT 1000\" );\n    }\n}\n\n\/** \u5165\u529b\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3 *\/\nfunction mls_validate_input( array $body, array $required_keys ) {\n    \/\/ product_slug \u2192 product_id \u3078\u6b63\u898f\u5316\uff08amu-ai-publisher \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u5bfe\u5fdc\uff09\n    if ( empty( $body['product_id'] ) &amp;&amp; ! empty( $body['product_slug'] ) ) {\n        $body['product_id'] = $body['product_slug'];\n    }\n\n    foreach ( $required_keys as $key ) {\n        if ( empty( $body[ $key ] ) ) {\n            return new WP_Error( 'missing_field', \"\u5fc5\u9808\u30d1\u30e9\u30e1\u30fc\u30bf\u304c\u4e0d\u8db3\u3057\u3066\u3044\u307e\u3059: {$key}\" );\n        }\n    }\n\n    \/\/ product_id\u306e\u7167\u5408\u306fGumroad verify\u306b\u4efb\u305b\u308b\u305f\u3081\u3053\u3053\u3067\u306f\u30c1\u30a7\u30c3\u30af\u3057\u306a\u3044\n    return true;\n}\n\n\/** Gumroad verify\u7528\u306eproduct_id\u3092\u53d6\u5f97\uff08DB\u8a2d\u5b9a\u5024\u3092\u512a\u5148\uff09 *\/\nfunction mls_get_product_id( array $body ): string {\n    \/\/ DB\u306b\u8a2d\u5b9a\u3055\u308c\u305fProduct ID\u3092\u512a\u5148\uff08Gumroad verify\u7528\uff09\n    $configured = get_option( 'mls_product_id', '' );\n    if ( $configured ) {\n        return trim( $configured );\n    }\n    \/\/ \u30d5\u30a9\u30fc\u30eb\u30d0\u30c3\u30af: \u30ea\u30af\u30a8\u30b9\u30c8\u306eproduct_id or product_slug\n    if ( ! empty( $body['product_id'] ) ) {\n        return sanitize_text_field( $body['product_id'] );\n    }\n    return sanitize_text_field( $body['product_slug'] ?? '' );\n}\n\n\/** \u30a8\u30e9\u30fc\u30ec\u30b9\u30dd\u30f3\u30b9 *\/\nfunction mls_json_error( string $code, string $message, int $status = 400 ) {\n    return new WP_REST_Response( [\n        'ok'      =&gt; false,\n        'status'  =&gt; $code,\n        'message' =&gt; $message,\n    ], $status );\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u7ba1\u7406\u753b\u9762: \u8a2d\u5b9a\u30da\u30fc\u30b8\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nadd_action( 'admin_menu', 'mls_admin_menu' );\nfunction mls_admin_menu() {\n    add_options_page(\n        'License Server \u8a2d\u5b9a',\n        'License Server',\n        'manage_options',\n        'mls-settings',\n        'mls_settings_page'\n    );\n}\n\nadd_action( 'admin_init', 'mls_register_settings' );\nfunction mls_register_settings() {\n    register_setting( 'mls_options', 'mls_product_id', [\n        'sanitize_callback' =&gt; function( $val ) { return trim( (string) $val ); },\n    ] );\n}\n\nfunction mls_settings_page() {\n    global $wpdb;\n    ?&gt;\n    &lt;div class=\"wrap\"&gt;\n        &lt;h1&gt;License Server \u8a2d\u5b9a&lt;\/h1&gt;\n        &lt;form method=\"post\" action=\"options.php\"&gt;\n            &lt;?php settings_fields( 'mls_options' ); ?&gt;\n            &lt;table class=\"form-table\"&gt;\n                &lt;tr&gt;\n                    &lt;th&gt;Gumroad Product ID&lt;\/th&gt;\n                    &lt;td&gt;\n                        &lt;input type=\"text\" name=\"mls_product_id\"\n                            value=\"&lt;?php echo esc_attr( get_option( 'mls_product_id' ) ); ?&gt;\"\n                            class=\"regular-text\" \/&gt;\n                        &lt;p class=\"description\"&gt;Gumroad\u7ba1\u7406\u753b\u9762\u306e\u300cUse your product ID to verify licenses\u300d\u306eID\uff08\u4f8b: xxxxxxxxxxxxxxxxxxx-X==\uff09&lt;\/p&gt;\n                    &lt;\/td&gt;\n                &lt;\/tr&gt;\n            &lt;\/table&gt;\n            &lt;?php submit_button(); ?&gt;\n        &lt;\/form&gt;\n\n        &lt;h2&gt;\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8&lt;\/h2&gt;\n        &lt;code&gt;&lt;?php echo esc_url( rest_url( 'mls\/v1\/license' ) ); ?&gt;&lt;\/code&gt;\n\n        &lt;h2&gt;\u30e9\u30a4\u30bb\u30f3\u30b9\u4e00\u89a7&lt;\/h2&gt;\n        &lt;?php\n        $licenses = $wpdb-&gt;get_results( \"SELECT * FROM {$wpdb-&gt;prefix}mls_licenses ORDER BY created_at DESC LIMIT 50\" );\n        if ( $licenses ) :\n        ?&gt;\n        &lt;table class=\"wp-list-table widefat striped\"&gt;\n            &lt;thead&gt;&lt;tr&gt;\n                &lt;th&gt;Key\u672b\u5c3e4\u6841&lt;\/th&gt;&lt;th&gt;Product ID&lt;\/th&gt;&lt;th&gt;Status&lt;\/th&gt;\n                &lt;th&gt;Email&lt;\/th&gt;&lt;th&gt;\u4f7f\u7528\u6570\/\u4e0a\u9650&lt;\/th&gt;&lt;th&gt;\u6700\u7d42\u78ba\u8a8d&lt;\/th&gt;\n            &lt;\/tr&gt;&lt;\/thead&gt;\n            &lt;tbody&gt;\n            &lt;?php foreach ( $licenses as $lic ) :\n                $count = mls_count_active_activations( $lic-&gt;license_key_hash );\n            ?&gt;\n                &lt;tr&gt;\n                    &lt;td&gt;****&lt;?php echo esc_html( $lic-&gt;license_key_last4 ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $lic-&gt;product_id ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $lic-&gt;status ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $lic-&gt;gumroad_email ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $count . '\/' . $lic-&gt;max_sites ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $lic-&gt;last_verified_at ); ?&gt;&lt;\/td&gt;\n                &lt;\/tr&gt;\n            &lt;?php endforeach; ?&gt;\n            &lt;\/tbody&gt;\n        &lt;\/table&gt;\n        &lt;?php else : ?&gt;\n        &lt;p&gt;\u307e\u3060\u30e9\u30a4\u30bb\u30f3\u30b9\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002&lt;\/p&gt;\n        &lt;?php endif; ?&gt;\n\n        &lt;h2&gt;\u6700\u8fd1\u306e\u30ed\u30b0&lt;\/h2&gt;\n        &lt;?php\n        $logs = $wpdb-&gt;get_results( \"SELECT * FROM {$wpdb-&gt;prefix}mls_logs ORDER BY id DESC LIMIT 50\" );\n        if ( $logs ) :\n        ?&gt;\n        &lt;table class=\"wp-list-table widefat striped\"&gt;\n            &lt;thead&gt;&lt;tr&gt;\n                &lt;th&gt;\u65e5\u6642&lt;\/th&gt;&lt;th&gt;Action&lt;\/th&gt;&lt;th&gt;Key\u672b\u5c3e4\u6841&lt;\/th&gt;&lt;th&gt;Domain&lt;\/th&gt;&lt;th&gt;Result&lt;\/th&gt;&lt;th&gt;Message&lt;\/th&gt;\n            &lt;\/tr&gt;&lt;\/thead&gt;\n            &lt;tbody&gt;\n            &lt;?php foreach ( $logs as $log ) : ?&gt;\n                &lt;tr&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $log-&gt;timestamp ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $log-&gt;action ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;****&lt;?php echo esc_html( $log-&gt;license_key_last4 ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $log-&gt;domain ); ?&gt;&lt;\/td&gt;\n                    &lt;td style=\"color:&lt;?php echo $log-&gt;result === 'ok' ? 'green' : 'red'; ?&gt;\"&gt;\n                        &lt;?php echo esc_html( $log-&gt;result ); ?&gt;&lt;\/td&gt;\n                    &lt;td&gt;&lt;?php echo esc_html( $log-&gt;message ); ?&gt;&lt;\/td&gt;\n                &lt;\/tr&gt;\n            &lt;?php endforeach; ?&gt;\n            &lt;\/tbody&gt;\n        &lt;\/table&gt;\n        &lt;?php else : ?&gt;\n        &lt;p&gt;\u30ed\u30b0\u306f\u3042\u308a\u307e\u305b\u3093\u3002&lt;\/p&gt;\n        &lt;?php endif; ?&gt;\n    &lt;\/div&gt;\n    &lt;?php\n}<\/code><\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">\u81ea\u4f5c\u30d7\u30e9\u30b0\u30a4\u30f3<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u8a8d\u8a3c\u90e8\u5206\u3060\u3051\u306e\u30b3\u30fc\u30c9\u3067\u3059\u3002\u8a2d\u5b9a\u753b\u9762\u30fb\u4fdd\u5b58\u51e6\u7406\u30fb\u5b9a\u671f\u5b9f\u884c\u30fb\u5546\u54c1\u3054\u3068\u306e\u6a5f\u80fd\u5236\u5fa1\u307e\u3067\u542b\u3080\u914d\u5e03\u7528\u30d7\u30e9\u30b0\u30a4\u30f3\u4e00\u5f0f\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-php\" data-lang=\"PHP\"><code>&lt;?php\n\/**\n * \u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\uff08\u516c\u958b\u30b5\u30f3\u30d7\u30eb\uff09\n *\n * \u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u5074\u306b\u7d44\u307f\u8fbc\u3080\u8a8d\u8a3c\u51e6\u7406\u3067\u3059\u3002\n * \u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306e\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306b activate \/ validate \/ deactivate \u3092\u9001\u4fe1\u3057\u307e\u3059\u3002\n *\n * File: inc\/license-client.php\n *\/\n\ndeclare(strict_types=1);\n\nif (! defined('ABSPATH')) {\n    exit;\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u30e9\u30a4\u30bb\u30f3\u30b9\u72b6\u614b\u306e\u7ba1\u7406\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction amu_ai_license_default_state(): array\n{\n    return [\n        'status'     =&gt; 'inactive',\n        'last_check' =&gt; '',\n        'domain'     =&gt; '',\n        'site_count' =&gt; 0,\n        'max_sites'  =&gt; 0,\n        'message'    =&gt; '',\n    ];\n}\n\nfunction amu_ai_license_get_state(): array\n{\n    $state = get_option('amu_ai_license_state', []);\n    return wp_parse_args(is_array($state) ? $state : [], amu_ai_license_default_state());\n}\n\nfunction amu_ai_license_update_state(array $state): void\n{\n    $current = amu_ai_license_get_state();\n    update_option('amu_ai_license_state', array_merge($current, $state), false);\n}\n\nfunction amu_ai_license_reset_state(): void\n{\n    update_option('amu_ai_license_state', amu_ai_license_default_state(), false);\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u8a2d\u5b9a\u5024\u306e\u53d6\u5f97\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/** \u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306e\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8URL *\/\nfunction amu_ai_license_get_api_url(): string\n{\n    $settings = get_option('amu_ai_settings', []);\n    return untrailingslashit((string) ($settings['license_api_url'] ?? ''));\n}\n\n\/** \u3053\u306e\u30b5\u30a4\u30c8\u306e\u30c9\u30e1\u30a4\u30f3\uff08\u6b63\u898f\u5316\u6e08\u307f\uff09 *\/\nfunction amu_ai_license_get_current_domain(): string\n{\n    $host = wp_parse_url(home_url('\/'), PHP_URL_HOST);\n    $host = is_string($host) ? strtolower($host) : '';\n    return preg_replace('\/^www\\.\/', '', $host) ?? $host;\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u30ea\u30af\u30a8\u30b9\u30c8\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/**\n * \u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306b action \u3092\u9001\u4fe1\u3059\u308b\u5171\u901a\u95a2\u6570\n *\n * @param string $action  activate \/ validate \/ deactivate\n * @return array|WP_Error \u30ec\u30b9\u30dd\u30f3\u30b9JSON\u914d\u5217 or WP_Error\n *\/\nfunction amu_ai_license_request(string $action)\n{\n    $settings    = get_option('amu_ai_settings', []);\n    $license_key = (string) ($settings['license_key'] ?? '');\n    $api_url     = amu_ai_license_get_api_url();\n\n    if ($license_key === '' || $api_url === '') {\n        return new WP_Error('amu_ai_license_missing_config', '\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u307e\u305f\u306fAPI\u306eURL\u304c\u672a\u8a2d\u5b9a\u3067\u3059\u3002');\n    }\n\n    $response = wp_remote_post($api_url, [\n        'timeout' =&gt; 10,\n        'headers' =&gt; ['Content-Type' =&gt; 'application\/json; charset=utf-8'],\n        'body'    =&gt; wp_json_encode([\n            'action'         =&gt; $action,\n            'product_slug'   =&gt; 'your-plugin-slug', \/\/ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30b9\u30e9\u30c3\u30b0\u306b\u5909\u66f4\n            'license_key'    =&gt; $license_key,\n            'site_url'       =&gt; home_url('\/'),\n            'plugin_version' =&gt; '1.0.0', \/\/ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306b\u5909\u66f4\n        ]),\n    ]);\n\n    if (is_wp_error($response)) {\n        return $response;\n    }\n\n    $code = (int) wp_remote_retrieve_response_code($response);\n    $body = (string) wp_remote_retrieve_body($response);\n    $data = json_decode($body, true);\n\n    if ($code &lt; 200 || $code &gt;= 300 || ! is_array($data)) {\n        return new WP_Error('amu_ai_license_invalid_response', '\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u304b\u3089\u306e\u5fdc\u7b54\u304c\u4e0d\u6b63\u3067\u3059\u3002');\n    }\n\n    return $data;\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u30ec\u30b9\u30dd\u30f3\u30b9\u3092DB\u306b\u4fdd\u5b58\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction amu_ai_license_store_response(array $data, string $fallback_status = 'inactive'): void\n{\n    amu_ai_license_update_state([\n        'status'     =&gt; (string) ($data['status'] ?? $fallback_status),\n        'last_check' =&gt; current_time('mysql'),\n        'domain'     =&gt; (string) ($data['domain'] ?? amu_ai_license_get_current_domain()),\n        'site_count' =&gt; (int) ($data['site_count'] ?? 0),\n        'max_sites'  =&gt; (int) ($data['max_sites'] ?? 0),\n        'message'    =&gt; (string) ($data['message'] ?? ''),\n    ]);\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u6709\u52b9\u6027\u30c1\u30a7\u30c3\u30af\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/**\n * \u30e9\u30a4\u30bb\u30f3\u30b9\u304c\u6709\u52b9\u304b\u3069\u3046\u304b\u3092\u5224\u5b9a\u3059\u308b\n *\n * - status \u304c 'active' \u3067\u3042\u308b\u3053\u3068\n * - \u6700\u7d42\u78ba\u8a8d\u304b\u30897\u65e5\u4ee5\u5185\u3067\u3042\u308b\u3053\u3068\uff08\u901a\u4fe1\u5931\u6557\u6642\u306e\u7336\u4e88\u671f\u9593\uff09\n *\n * \u6709\u6599\u6a5f\u80fd\u306e\u30ac\u30fc\u30c9\u306b\u4f7f\u3046: if ( ! amu_ai_license_is_recently_valid() ) { return; }\n *\/\nfunction amu_ai_license_is_recently_valid(): bool\n{\n    $state = amu_ai_license_get_state();\n\n    if (($state['status'] ?? '') !== 'active') {\n        return false;\n    }\n\n    $last_check = strtotime((string) ($state['last_check'] ?? ''));\n    if (! $last_check) {\n        return false;\n    }\n\n    \/\/ 7\u65e5\u4ee5\u5185\u306a\u3089\u6709\u52b9\uff08\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u304c\u4e00\u6642\u7684\u306b\u30c0\u30a6\u30f3\u3057\u3066\u3082\u7336\u4e88\u3092\u6301\u3064\uff09\n    return $last_check &gt;= (time() - DAY_IN_SECONDS * 7);\n}\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u7ba1\u7406\u753b\u9762\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u30cf\u30f3\u30c9\u30e9\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/** \u6709\u52b9\u5316\u30dc\u30bf\u30f3\u62bc\u4e0b *\/\nfunction amu_ai_license_handle_activate(): void\n{\n    if (! current_user_can('manage_options')) {\n        wp_die('Permission denied.');\n    }\n    check_admin_referer('amu_ai_license_activate');\n\n    $response = amu_ai_license_request('activate');\n\n    if (is_wp_error($response)) {\n        amu_ai_license_set_notice('error', $response-&gt;get_error_message());\n    } else {\n        amu_ai_license_store_response($response, 'inactive');\n        amu_ai_license_set_notice('success', (string) ($response['message'] ?? '\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u6709\u52b9\u5316\u3057\u307e\u3057\u305f\u3002'));\n    }\n\n    wp_safe_redirect(wp_get_referer() ?: admin_url('options-general.php?page=your-plugin-license'));\n    exit;\n}\nadd_action('admin_post_amu_ai_license_activate', 'amu_ai_license_handle_activate');\n\n\/** \u691c\u8a3c\u30dc\u30bf\u30f3\u62bc\u4e0b *\/\nfunction amu_ai_license_handle_validate(): void\n{\n    if (! current_user_can('manage_options')) {\n        wp_die('Permission denied.');\n    }\n    check_admin_referer('amu_ai_license_validate');\n\n    $response = amu_ai_license_request('validate');\n\n    if (is_wp_error($response)) {\n        amu_ai_license_set_notice('error', $response-&gt;get_error_message());\n    } else {\n        amu_ai_license_store_response($response, ! empty($response['valid']) ? 'active' : 'inactive');\n        amu_ai_license_set_notice('success', (string) ($response['message'] ?? '\u30e9\u30a4\u30bb\u30f3\u30b9\u72b6\u614b\u3092\u78ba\u8a8d\u3057\u307e\u3057\u305f\u3002'));\n    }\n\n    wp_safe_redirect(wp_get_referer() ?: admin_url('options-general.php?page=your-plugin-license'));\n    exit;\n}\nadd_action('admin_post_amu_ai_license_validate', 'amu_ai_license_handle_validate');\n\n\/** \u89e3\u9664\u30dc\u30bf\u30f3\u62bc\u4e0b *\/\nfunction amu_ai_license_handle_deactivate(): void\n{\n    if (! current_user_can('manage_options')) {\n        wp_die('Permission denied.');\n    }\n    check_admin_referer('amu_ai_license_deactivate');\n\n    $response = amu_ai_license_request('deactivate');\n\n    if (is_wp_error($response)) {\n        amu_ai_license_set_notice('error', $response-&gt;get_error_message());\n    } else {\n        amu_ai_license_store_response($response, 'inactive');\n        amu_ai_license_set_notice('success', (string) ($response['message'] ?? '\u3053\u306e\u30b5\u30a4\u30c8\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u89e3\u9664\u3057\u307e\u3057\u305f\u3002'));\n    }\n\n    wp_safe_redirect(wp_get_referer() ?: admin_url('options-general.php?page=your-plugin-license'));\n    exit;\n}\nadd_action('admin_post_amu_ai_license_deactivate', 'amu_ai_license_handle_deactivate');\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u7ba1\u7406\u753b\u9762\u306e\u901a\u77e5\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction amu_ai_license_set_notice(string $type, string $message): void\n{\n    if (! is_user_logged_in()) {\n        return;\n    }\n    set_transient('amu_ai_license_notice_' . get_current_user_id(), [\n        'type'    =&gt; $type,\n        'message' =&gt; $message,\n    ], 60);\n}\n\nfunction amu_ai_license_render_notice(): void\n{\n    if (! is_user_logged_in()) {\n        return;\n    }\n    $key    = 'amu_ai_license_notice_' . get_current_user_id();\n    $notice = get_transient($key);\n    if (! is_array($notice) || empty($notice['message'])) {\n        return;\n    }\n    delete_transient($key);\n    $class = ($notice['type'] ?? 'success') === 'error' ? 'notice-error' : 'notice-success';\n    echo '&lt;div class=\"notice ' . esc_attr($class) . '\"&gt;&lt;p&gt;' . esc_html((string) $notice['message']) . '&lt;\/p&gt;&lt;\/div&gt;';\n}\nadd_action('admin_notices', 'amu_ai_license_render_notice');\n\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ \u6709\u6599\u6a5f\u80fd\u306e\u30ac\u30fc\u30c9\u4f8b\n\/\/ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\/**\n * AJAX\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u5171\u901a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u95a2\u6570\u306b\u30e9\u30a4\u30bb\u30f3\u30b9\u30c1\u30a7\u30c3\u30af\u3092\u8ffd\u52a0\u3059\u308b\u4f8b\n *\n * function your_plugin_validate_request(): void\n * {\n *     check_ajax_referer('your_plugin_nonce', 'nonce');\n *\n *     \/\/ \u30e9\u30a4\u30bb\u30f3\u30b9\u30c1\u30a7\u30c3\u30af\n *     if ( ! amu_ai_license_is_recently_valid() ) {\n *         wp_send_json_error([\n *             'message' =&gt; '\u30e9\u30a4\u30bb\u30f3\u30b9\u304c\u6709\u52b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30e9\u30a4\u30bb\u30f3\u30b9\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002'\n *         ], 403);\n *     }\n *\n *     \/\/ \u4ee5\u964d\u306f\u901a\u5e38\u306e\u6a29\u9650\u30c1\u30a7\u30c3\u30af\u7b49\n * }\n *\/<\/code><\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">\u78ba\u8a8d\u3057\u305f\u7bc4\u56f2\u3068\u672a\u78ba\u8a8d\u306e\u70b9\u30fb\u623b\u3057\u65b9<\/h2>\n\n\n<p class=\"wp-block-paragraph\">2026\u5e7410\u670823\u65e5\u306e\u898b\u76f4\u3057\u3067\u306f\u3001\u672c\u6587\u3068\u63b2\u8f09\u30b3\u30fc\u30c9\u3092\u5168\u4f53\u306b\u308f\u305f\u3063\u3066\u8aad\u307f\u3001Gumroad\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u516c\u5f0f\u6848\u5185\u3068WordPress\u306eREST URL\u751f\u6210\u51e6\u7406\u306b\u7167\u5408\u3057\u307e\u3057\u305f\u3002\u8cfc\u5165\u3084API\u3078\u306e\u5b9f\u901a\u4fe1\u3001WordPress\u4e0a\u3067\u306e\u30b3\u30fc\u30c9\u5b9f\u884c\u3001\u753b\u9762\u78ba\u8a8d\u306f\u884c\u3063\u3066\u3044\u307e\u305b\u3093\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">WordPress\u30fbPHP\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u5225\u306e\u5b9f\u884c\u7d50\u679c\u3001\u6709\u52b9\u5316\u30fb\u691c\u8a3c\u30fb\u89e3\u9664\u30683\u30b5\u30a4\u30c8\u4e0a\u9650\u306e\u5b9f\u969b\u306e\u5224\u5b9a\u3001\u540c\u6642\u30a2\u30af\u30bb\u30b9\u6642\u306e\u8ca0\u8377\u3001\u8fd4\u91d1\u30fb\u89e3\u7d04\u306e\u53cd\u6620\u3068Webhook\u9023\u643a\u3001\u30c1\u30fc\u30e0\u5411\u3051seats\u8ab2\u91d1\u9023\u52d5\u306f\u4eca\u56de\u672a\u691c\u8a3c\u3067\u3059\u3002\u5b9f\u904b\u7528\u306e\u524d\u306b\u3001\u691c\u8a3c\u74b0\u5883\u3067\u8cfc\u5165\u72b6\u614b\u3068\u5fdc\u7b54\u3092\u7167\u5408\u3057\u3066\u304f\u3060\u3055\u3044\u3002API\u306e\u4ed5\u69d8\u306f<a href=\"https:\/\/gumroad.com\/api#licenses\" rel=\"noopener noreferrer\" target=\"_blank\">Gumroad API\u516c\u5f0f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\uff08Licenses\uff09<\/a>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">\u5143\u306b\u623b\u3059\u5834\u5408\u306f\u3001\u5909\u66f4\u524d\u306e\u8ca9\u58f2\u30d7\u30e9\u30b0\u30a4\u30f3\u3068\u8a2d\u5b9a\u3092\u5fa9\u5143\u3057\u3001\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u5074\u306e\u300cMotoki License Server\u300d\u3092\u7121\u52b9\u5316\u3057\u307e\u3059\u3002\u8a8d\u8a3c\u306e\u306a\u3044\u30d3\u30eb\u30c9\u3078\u623b\u3059\u3068\u6709\u6599\u6a5f\u80fd\u3092\u5236\u9650\u3067\u304d\u306a\u304f\u306a\u308b\u305f\u3081\u3001\u516c\u958b\u7bc4\u56f2\u3082\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30e9\u30a4\u30bb\u30f3\u30b9\u30fb\u6709\u52b9\u5316\u30b5\u30a4\u30c8\u30fb\u30ed\u30b0\u306e\u30c6\u30fc\u30d6\u30eb\u306f\u5fa9\u65e7\u7528\u306b\u4fdd\u6301\u3057\u3001\u524a\u9664\u3059\u308b\u524d\u306b\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3068\u4fdd\u6301\u5bfe\u8c61\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">\u307e\u3068\u3081<\/h2>\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u69cb\u6210\u306e\u30dd\u30a4\u30f3\u30c8\u306f\u4ee5\u4e0b\u306e\u3068\u304a\u308a\u3067\u3059\u3002<\/p>\n\n\n<ul class=\"wp-block-list is-style-num_circle\">\n<li><strong>\u81ea\u524d\u30b5\u30fc\u30d0\u30fc\u3068Gumroad\u3092\u4f75\u7528<\/strong>: WordPress\u30fbMySQL\u306e\u4fdd\u5b88\u3068Gumroad\u3078\u306e\u901a\u4fe1\u304c\u5fc5\u8981<\/li>\n\n\n<li><strong>Gumroad\u306everify API\u306fAPI\u30ad\u30fc\u4e0d\u8981<\/strong>: product_id\u3068license_key\u3060\u3051\u3067\u691c\u8a3c\u3067\u304d\u308b<\/li>\n\n\n<li><strong>\u5546\u54c1\u8b58\u5225\u5b50\u3092\u7167\u5408<\/strong>: product_id\u306b\u306f\u5546\u54c1\u7de8\u96c6\u753b\u9762\u306eProduct ID\u3092\u4f7f\u3046<\/li>\n\n\n<li><strong>\u8a2d\u5b9a\u4fdd\u5b58\u306f\u539f\u56e0\u3092\u5207\u308a\u5206\u3051\u308b<\/strong>: \u7279\u5b9a\u30d7\u30e9\u30b0\u30a4\u30f3\u3068\u6c7a\u3081\u3064\u3051\u305a\u3001\u5fdc\u7b54\u30fb\u6a29\u9650\u30fb\u30ed\u30b0\u3092\u78ba\u8a8d<\/li>\n\n\n<li><strong>ZIP\u306f\u69cb\u9020\u3092\u78ba\u8a8d<\/strong>: \u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u304c\u542b\u307e\u308c\u308b\u5834\u5408\u3060\u3051\u3001\u5c55\u958b\u7d50\u679c\u3092\u8abf\u3079\u3066\u4fee\u6b63<\/li>\n<\/ul>\n\n\n<p class=\"wp-block-paragraph\">\u8ca9\u58f2\u898f\u6a21\u304c\u5c0f\u3055\u304f\u3066\u3082\u3001\u8aa4\u3063\u305f\u6709\u52b9\u30fb\u7121\u52b9\u5224\u5b9a\u3084\u540c\u6642\u767b\u9332\u306b\u3088\u308b\u4e0a\u9650\u8d85\u904e\u306f\u8d77\u3053\u308a\u5f97\u307e\u3059\u3002\u4e0a\u8a18\u306e\u672a\u5bfe\u5fdc\u90e8\u5206\u3092\u89e3\u6d88\u3057\u3001\u691c\u8a3c\u7d50\u679c\u3092\u8a18\u9332\u3057\u3066\u304b\u3089\u904b\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\">Webhook\u9023\u643a\u3084seats\u8ab2\u91d1\u9023\u52d5\u306f\u672a\u5b9f\u88c5\u3067\u3059\u3002\u5fc5\u8981\u306a\u5834\u5408\u306f\u901a\u77e5\u306e\u771f\u6b63\u6027\u3001\u91cd\u8907\u30fb\u9806\u5e8f\u9006\u8ee2\u3001\u518d\u9001\u3001\u5b9a\u671f\u7167\u5408\u307e\u3067\u542b\u3081\u3066\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u8a18\u4e8b\u3067\u7d39\u4ecb\u3057\u3066\u3044\u308b\u30b3\u30fc\u30c9\u306f\u3001GitHub\u306e<a href=\"https:\/\/github.com\/MOTOKI-LLC\/WAZA-code\/tree\/main\/wordpress-plugin-gumroad-license-authentication\">MOTOKI-LLC\/WAZA-code<\/a>\u306b\u3082\u307e\u3068\u3081\u3066\u3044\u307e\u3059\u3002 \u672c\u6587\u306e\u4fee\u6b63\u3068GitHub\u5074\u306e\u540c\u671f\u306f\u4eca\u56de\u78ba\u8a8d\u3057\u3066\u3044\u307e\u305b\u3093\u3002<\/p>\n\n\n<h2 class=\"wp-block-heading\">\u3088\u304f\u3042\u308b\u8cea\u554f\uff1aGumroad\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u306e\u5b9f\u88c5<\/h2>\n\n\n<h3 class=\"wp-block-heading\">\u3053\u306e\u8a18\u4e8b\u3067\u306f\u3001\u3069\u3093\u306a\u69cb\u6210\u3067\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u3092\u5b9f\u88c5\u3057\u307e\u3059\u304b\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">Gumroad\u3067\u8cfc\u5165\u60c5\u5831\u3092\u691c\u8a3c\u3057\u3001\u81ea\u524d\u306eWordPress\u3068MySQL\u3067\u5229\u7528\u30c9\u30e1\u30a4\u30f3\u3092\u8a18\u9332\u3059\u308b\u53c2\u8003\u69cb\u6210\u3067\u3059\u30023\u30c9\u30e1\u30a4\u30f3\u3092\u60f3\u5b9a\u3057\u3066\u3044\u307e\u3059\u304c\u3001\u540c\u6642\u767b\u9332\u6642\u306e\u4e0a\u9650\u4fdd\u8a3c\u3084\u5b9a\u671f\u518d\u8a8d\u8a3c\u306a\u3069\u306f\u672a\u5b9f\u88c5\u3067\u3059\u3002Gumroad\u306e\u8ca9\u58f2\u624b\u6570\u6599\u3068\u30b5\u30fc\u30d0\u30fc\u306e\u904b\u7528\u8cbb\u306f\u5225\u9014\u304b\u304b\u308a\u307e\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">Gumroad\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u691c\u8a3cAPI\u306f\u3001API\u30ad\u30fc\u304c\u5fc5\u8981\u3067\u3059\u304b\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u63b2\u8f09\u3059\u308b\u691c\u8a3cAPI\u306fproduct_id\u3068license_key\u3092\u9001\u308a\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u3092\u4f7f\u3044\u307e\u305b\u3093\u3002increment_uses_count=false\u3067Gumroad\u306e\u4f7f\u7528\u56de\u6570\u3092\u5897\u3084\u3055\u305a\u3001\u30c9\u30e1\u30a4\u30f3\u6570\u3092\u81ea\u524d\u3067\u7ba1\u7406\u3059\u308b\u8a2d\u8a08\u3067\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">Product ID\u3092\u9593\u9055\u3048\u3084\u3059\u3044\u3068\u805e\u304d\u307e\u3057\u305f\u3002\u3069\u308c\u3092\u4f7f\u3044\u307e\u3059\u304b\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u5546\u54c1\u7de8\u96c6\u753b\u9762\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306e\u30d6\u30ed\u30c3\u30af\u306b\u8868\u793a\u3055\u308c\u308bProduct ID\u3092\u305d\u306e\u307e\u307e\u4f7f\u3044\u307e\u3059\u3002\u5546\u54c1URL\u306e\u30b9\u30e9\u30c3\u30b0\u3084\u8cfc\u5165\u8005\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u3068\u306f\u5225\u306e\u5024\u3067\u3059\u3002\u672b\u5c3e\u306e\u6587\u5b57\u3060\u3051\u3067\u6b63\u5426\u3092\u5224\u65ad\u3057\u307e\u305b\u3093\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30b5\u30fc\u30d0\u30fc\u306eWordPress\u3067\u3001\u5fc5\u305a\u884c\u3046\u3053\u3068\u306f\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u8a8d\u8a3c\u30b5\u30fc\u30d0\u30fc\u306eHTTPS\u3068Product ID\u8a2d\u5b9a\u3092\u78ba\u8a8d\u3057\u3001\u5b9f\u969b\u306eREST URL\u3078POST\u3057\u3066\u691c\u8a3c\u3057\u307e\u3059\u3002\u30d1\u30fc\u30de\u30ea\u30f3\u30af\u3092\u300c\u6295\u7a3f\u540d\u300d\u306b\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u6709\u52b9\u5316\u51e6\u7406\u306b\u3088\u308b3\u30c6\u30fc\u30d6\u30eb\u306e\u4f5c\u6210\u3082\u3001DB\u30a8\u30e9\u30fc\u304c\u306a\u3044\u304b\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u306f\u3001\u3069\u3046\u4fdd\u5b58\u3055\u308c\u307e\u3059\u304b\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u30b5\u30fc\u30d0\u30fc\u5074\u306fSHA-256\u30cf\u30c3\u30b7\u30e5\u3068\u672b\u5c3e4\u6587\u5b57\u3092\u4fdd\u5b58\u3057\u307e\u3059\u3002\u4e00\u65b9\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306f\u8a2d\u5b9a\u304b\u3089\u5e73\u6587\u30ad\u30fc\u3092\u8aad\u307f\u51fa\u3057\u307e\u3059\u3002\u8cfc\u5165\u8005\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306a\u3069\u3082\u542b\u3081\u3001DB\u30fb\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30fb\u30ed\u30b0\u3078\u306e\u30a2\u30af\u30bb\u30b9\u3092\u7ba1\u7406\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u7ba1\u7406\u753b\u9762\u306e\u8a2d\u5b9a\u304c\u4fdd\u5b58\u3055\u308c\u306a\u3044\u3068\u304d\u306f\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u4fdd\u5b58\u30ea\u30af\u30a8\u30b9\u30c8\u3001\u7ba1\u7406\u8005\u6a29\u9650\u3001nonce\u3001\u8a2d\u5b9a\u767b\u9332\u3001WAF\u3084\u30b5\u30fc\u30d0\u30fc\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002\u7279\u5b9a\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u539f\u56e0\u3068\u6c7a\u3081\u3064\u3051\u305f\u308a\u3001\u539f\u56e0\u4e0d\u660e\u306e\u307e\u307eSQL\u3067\u4e0a\u66f8\u304d\u3057\u305f\u308a\u3059\u308b\u624b\u9806\u306b\u306f\u3057\u307e\u305b\u3093\u3002<\/p>\n\n\n<h3 class=\"wp-block-heading\">\u3053\u306e\u8a18\u4e8b\u306e\u30b3\u30fc\u30c9\u306f\u3001\u52d5\u4f5c\u78ba\u8a8d\u6e08\u307f\u3067\u3059\u304b\uff1f<\/h3>\n\n\n<p class=\"wp-block-paragraph\">\u672c\u6587\u3068\u30b3\u30fc\u30c9\u306e\u8aad\u307f\u53d6\u308a\u3001\u516c\u5f0f\u8cc7\u6599\u3068\u306e\u7167\u5408\u307e\u3067\u3067\u3059\u3002Gumroad\u3078\u306e\u5b9f\u901a\u4fe1\u3001\u8cfc\u5165\u30fb\u8fd4\u91d1\u30fb\u5931\u52b9\u30fb\u89e3\u9664\u30fb\u4e0a\u9650\u30fb\u540c\u6642\u767b\u9332\u306e\u30c6\u30b9\u30c8\u3084\u753b\u9762\u78ba\u8a8d\u306f\u5b9f\u65bd\u3057\u3066\u3044\u307e\u305b\u3093\u3002\u5b9a\u671f\u518d\u8a8d\u8a3c\u3084\u901a\u4fe1\u969c\u5bb3\u306e\u533a\u5225\u306a\u3069\u65e2\u77e5\u306e\u672a\u5bfe\u5fdc\u90e8\u5206\u3092\u4fee\u6b63\u3057\u305f\u3046\u3048\u3067\u3001\u691c\u8a3c\u74b0\u5883\u3067\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>WordPress\u306e\u6709\u6599\u30d7\u30e9\u30b0\u30a4\u30f3\u3092Gumroad\u3067\u8ca9\u58f2\u3059\u308b\u5834\u5408\u3001\u30e9\u30a4\u30bb\u30f3\u30b9\u8a8d\u8a3c\u306e\u4ed5\u7d44\u307f\u3092\u3069\u3046\u4f5c\u308b\u304b\u304c\u8ab2\u984c\u306b\u306a\u308a\u307e\u3059\u3002 \u3053\u306e\u8a18\u4e8b\u3067\u306f\u3001Gumroad\u3067\u8cfc\u5165\u60c5\u5831\u3092\u691c\u8a3c\u3057\u3001\u81ea\u524d\u306eWordPress REST API\u3068MySQ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":27861,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"swell_btn_cv_data":"","book_review_data":"","footnotes":"","ssp_meta_title":"Gumroad\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u8a8d\u8a3c\u3092\u81ea\u4f5cWP\u306b\u5b9f\u88c5","ssp_meta_description":"Gumroad\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30ad\u30fc\u691c\u8a3cAPI\u3068\u81ea\u4f5cWordPress REST API\u30b5\u30fc\u30d0\u30fc\u3092\u9023\u643a\u3055\u305b\u3001\u30d7\u30e9\u30b0\u30a4\u30f3\u8a8d\u8a3c\u3092\u5b9f\u88c5\u3059\u308b4\u3064\u306e\u30b9\u30c6\u30c3\u30d7\u3092\u89e3\u8aac\u3002\u6700\u59273\u30b5\u30a4\u30c8\u307e\u3067\u306e\u7ba1\u7406\u65b9\u6cd5\u3084\u3001\u8a8d\u8a3c\u7528Product ID\u306e\u78ba\u8a8d\u624b\u9806\u3092\u63b2\u8f09\u3057\u3066\u3044\u307e\u3059\u3002"},"categories":[111],"tags":[],"area":[],"class_list":["post-27850","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-plugin"],"_links":{"self":[{"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/posts\/27850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/comments?post=27850"}],"version-history":[{"count":8,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/posts\/27850\/revisions"}],"predecessor-version":[{"id":32116,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/posts\/27850\/revisions\/32116"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/media\/27861"}],"wp:attachment":[{"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/media?parent=27850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/categories?post=27850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/tags?post=27850"},{"taxonomy":"area","embeddable":true,"href":"https:\/\/motoki-design.co.jp\/wordpress\/wp-json\/wp\/v2\/area?post=27850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}