RestApiPaypalService.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. package com.fdkankan.pay.util.paypal.restApi;
  2. import cn.hutool.http.Header;
  3. import cn.hutool.http.HttpRequest;
  4. import cn.hutool.http.HttpResponse;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  7. import com.fasterxml.jackson.core.JsonProcessingException;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9. import com.fdkankan.pay.entity.PaypalConfig;
  10. import com.fdkankan.pay.service.IPaypalConfigService;
  11. import com.fdkankan.pay.util.CacheUtil;
  12. import com.fdkankan.pay.util.paypal.restApi.vo.EventTypeVo;
  13. import com.fdkankan.pay.util.paypal.restApi.vo.Product;
  14. import com.fdkankan.pay.util.paypal.restApi.vo.WebhookVo;
  15. import com.fdkankan.pay.util.paypal.restApi.vo.plan.*;
  16. import com.fdkankan.pay.util.paypal.restApi.vo.subscription.*;
  17. import com.paypal.api.payments.EventType;
  18. import com.paypal.api.payments.Links;
  19. import com.paypal.api.payments.Webhook;
  20. import com.paypal.api.payments.WebhookList;
  21. import com.paypal.base.rest.APIContext;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.apache.commons.lang.StringUtils;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.stereotype.Service;
  26. import javax.annotation.PostConstruct;
  27. import java.io.IOException;
  28. import java.io.InputStream;
  29. import java.io.OutputStreamWriter;
  30. import java.net.HttpURLConnection;
  31. import java.net.URL;
  32. import java.time.*;
  33. import java.util.*;
  34. @Service
  35. @Slf4j
  36. public class RestApiPaypalService {
  37. @Autowired
  38. IPaypalConfigService paypalConfigService;
  39. /**
  40. * 启动创建webhooks
  41. * https://testeur.4dkankan.com/service/pay/paypal/webhook
  42. */
  43. @PostConstruct
  44. public void createWebhooks() {
  45. log.info("--------------项目启动初始化webhook-------------");
  46. List<PaypalConfig> list = paypalConfigService.list();
  47. for (PaypalConfig paypalConfig : list) {
  48. if(StringUtils.isBlank(paypalConfig.getWebhookId())){
  49. try {
  50. Map<String,String> map = new HashMap<>(4);
  51. map.put("Content-Type","application/json");
  52. WebhookVo webhookVo = new WebhookVo();
  53. webhookVo.setUrl(paypalConfig.getWebhookHost() +"/service/pay/paypal/webhook");
  54. webhookVo.getEvent_types().add(new EventTypeVo("CATALOG.PRODUCT.CREATED"));
  55. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.CREATED"));
  56. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.ACTIVATED"));
  57. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.CREATED"));
  58. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.EXPIRED"));
  59. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.SUSPENDED"));
  60. webhookVo.getEvent_types().add(new EventTypeVo("PAYMENT.SALE.COMPLETED"));
  61. String string = JSONObject.toJSONString(webhookVo);
  62. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/notifications/webhooks")
  63. .addHeaders(map)
  64. .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret())
  65. .body(string)
  66. .execute().body();
  67. log.info("paypal-createWebhooks:{}",body);
  68. JSONObject resp = JSONObject.parseObject(body);
  69. String webhookId = resp.getString("id");
  70. paypalConfig.setWebhookId(webhookId);
  71. LambdaUpdateWrapper<PaypalConfig> wrapper = new LambdaUpdateWrapper<>();
  72. wrapper.eq(PaypalConfig::getId,paypalConfig.getId());
  73. wrapper.set(PaypalConfig::getWebhookId,webhookId);
  74. paypalConfigService.update(wrapper);
  75. }catch (Exception e){
  76. log.info("paypal-createWebhooks:error:",e);
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * 获取token
  83. */
  84. public static String getToken(PaypalConfig paypalConfig) {
  85. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/oauth2/token")
  86. .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret())
  87. .form("grant_type", "client_credentials")
  88. .execute().body();
  89. JSONObject jsonObject = JSONObject.parseObject(body);
  90. return jsonObject.get("access_token").toString();
  91. }
  92. /**
  93. * 创建商品
  94. */
  95. public String createProduct(PaypalConfig paypalConfig,Product product) {
  96. try {
  97. Map<String,String> map = new HashMap<>(4);
  98. map.put("Content-Type","application/json");
  99. map.put("Authorization",getToken(paypalConfig));
  100. // map.put("PayPal-Request-Id","PLAN-18062019-001");
  101. String string = new ObjectMapper().writeValueAsString(product);
  102. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/catalogs/products")
  103. .addHeaders(map)
  104. .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret())
  105. .body(string)
  106. .execute().body();
  107. log.info("paypal-createProduct:{}",body);
  108. JSONObject jsonObject = JSONObject.parseObject(body);
  109. return jsonObject.getString("id");
  110. }catch (Exception e){
  111. log.info("paypal-createProduct:error:",e);
  112. }
  113. return null;
  114. }
  115. /**
  116. * 创建计划
  117. *
  118. */
  119. public String createPlan(PaypalConfig paypalConfig,PlanVo planVo) {
  120. try {
  121. String dateTime = LocalDateTime.now().toString();
  122. Map<String,String> map = new HashMap<>(4);
  123. map.put("Content-Type","application/json");
  124. map.put("Authorization",getToken(paypalConfig));
  125. // map.put("PayPal-Request-Id","PLAN-18062019-001");
  126. PayPalSubscriptionPlanParam planParam = new PayPalSubscriptionPlanParam();
  127. List<BillingCycles> list = new ArrayList<>();
  128. BillingCycles billingCycles = new BillingCycles();
  129. billingCycles.setTenureType("REGULAR");
  130. billingCycles.setSequence(1);
  131. billingCycles.setTotalCycles(0);
  132. //计费周期
  133. Frequency frequency = new Frequency();
  134. frequency.setIntervalUnit(planVo.getTimeUnit());
  135. frequency.setIntervalCount(1);
  136. PricingScheme pricingScheme = new PricingScheme();
  137. pricingScheme.setVersion(1);
  138. pricingScheme.setCreateTime(dateTime);
  139. //定价
  140. FixedPrice fixedPrice = new FixedPrice();
  141. fixedPrice.setCurrencyCode(planVo.getCurrencyCode());
  142. fixedPrice.setValue(planVo.getPrice());
  143. pricingScheme.setFixedPrice(fixedPrice);
  144. billingCycles.setFrequency(frequency);
  145. billingCycles.setPricingScheme(pricingScheme);
  146. list.add(billingCycles);
  147. // 付款偏好
  148. PaymentPreferences paymentPreferences = new PaymentPreferences();
  149. paymentPreferences.setAutoBillOutstanding(true);
  150. paymentPreferences.setPaymentFailureThreshold(3);
  151. paymentPreferences.setSetupFeeFailureAction("CANCEL");
  152. SetupFee setupFee = new SetupFee();
  153. setupFee.setCurrencyCode(planVo.getCurrencyCode());
  154. setupFee.setValue("0");
  155. paymentPreferences.setSetupFee(setupFee);
  156. // 税率
  157. Taxes taxes = new Taxes();
  158. taxes.setInclusive(true);
  159. taxes.setPercentage("0");
  160. planParam.setTaxes(taxes);
  161. planParam.setPaymentPreferences(paymentPreferences);
  162. planParam.setBillingCycles(list);
  163. planParam.setProductId(planVo.getProductId());
  164. planParam.setName(planVo.getPlanName());
  165. planParam.setStatus("ACTIVE");
  166. planParam.setDescription(planVo.getPlanName());
  167. planParam.setCreateTime(dateTime);
  168. planParam.setUpdateTime(dateTime);
  169. String string = new ObjectMapper().writeValueAsString(planParam);
  170. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/plans")
  171. .addHeaders(map)
  172. .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret())
  173. .body(string)
  174. .execute().body();
  175. log.info("paypal-createPlan:{}",body);
  176. JSONObject planObj = JSONObject.parseObject(body);
  177. return planObj.getString("id");
  178. }catch (Exception e){
  179. log.info("paypal-createPlan:error:",e);
  180. }
  181. return null;
  182. }
  183. /**
  184. * 处理订阅参数
  185. *
  186. * @param planId
  187. * @return
  188. */
  189. private String handlerSubsParam(String planId,ApplicationContext applicationContext) {
  190. CompanyVo companyVo = new CompanyVo();
  191. SubscriptionDTO subscriptionDTO = new SubscriptionDTO();
  192. subscriptionDTO.setPlanId(planId);
  193. // subscriptionDTO.setQuantity("10");
  194. // subscriptionDTO.setShippingAmount("10");
  195. // subscriptionDTO.setStartTime(new Date());
  196. // subscriptionDTO.setQuantity("10");
  197. Subscriber subscriber = new Subscriber();
  198. SubscriberName subscriberName = new SubscriberName();
  199. subscriberName.setGiven_name(companyVo.getName());
  200. subscriberName.setSurname(companyVo.getName());
  201. subscriber.setName(subscriberName);
  202. subscriber.setEmailAddress(companyVo.getEmail());
  203. ShippingAddress shippingAddress = new ShippingAddress();
  204. shippingAddress.setAddress(new Address(companyVo.getAddress(),"","","","","C2"));
  205. shippingAddress.setName(new Name(companyVo.getName()));
  206. subscriber.setShippingAddress(shippingAddress);
  207. subscriptionDTO.setSubscriber(subscriber);
  208. subscriptionDTO.setApplicationContext(applicationContext);
  209. String string = "";
  210. try {
  211. string = new ObjectMapper().writeValueAsString(subscriptionDTO);
  212. // System.out.println(string);
  213. } catch (JsonProcessingException e) {
  214. e.printStackTrace();
  215. }
  216. return string;
  217. }
  218. /**
  219. * 创建订阅
  220. */
  221. public SubscriptionVo createSubscription(PaypalConfig paypalConfig,String planId) {
  222. Map<String,String> map = new HashMap<>(4);
  223. map.put("Content-Type","application/json");
  224. map.put("Authorization",getToken(paypalConfig));
  225. // P-7EG815794T029494CMFR77TA
  226. // String planId = "P-4ND94871NA4029913MFSTSXI";
  227. ApplicationContext applicationContext = new ApplicationContext();
  228. applicationContext.setCancelUrl(paypalConfig.getCancelUrl());
  229. applicationContext.setReturnUrl(paypalConfig.getSuccessUrl());
  230. applicationContext.setPaymentMethod(new PaymentMethod());
  231. String string = handlerSubsParam(planId,applicationContext);
  232. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/subscriptions")
  233. .addHeaders(map)
  234. .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret())
  235. .body(string)
  236. .execute().body();
  237. JSONObject jsonObject = JSONObject.parseObject(body);
  238. log.info("createSubscription-resp:{}",jsonObject);
  239. String id = jsonObject.getString("id");
  240. List<com.paypal.api.payments.Links> links = JSONObject.parseArray(jsonObject.get("links").toString(), com.paypal.api.payments.Links.class);
  241. Links links1 = links.stream().filter(o -> "approve".equals(o.getRel())).findFirst()
  242. .orElseThrow(() -> new RuntimeException("创建订阅失败"));
  243. String href = links1.getHref();
  244. SubscriptionVo vo = new SubscriptionVo(id, href);
  245. return vo;
  246. }
  247. /**
  248. * 取消订阅
  249. */
  250. public void cancelSubscriptions(PaypalConfig paypalConfig, String subscriptionsId) {
  251. Map<String,String> map = new HashMap<>(4);
  252. map.put("Content-Type","application/json");
  253. map.put("Authorization",getToken(paypalConfig));
  254. HttpResponse response = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/subscriptions/"+subscriptionsId+"/cancel")
  255. .addHeaders(map)
  256. .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret())
  257. .execute();
  258. // 订阅正常创建
  259. log.info("resp:{}",response);
  260. if (response.getStatus() == 201) {
  261. JSONObject respObj = JSONObject.parseObject(response.body());
  262. System.out.println(respObj);
  263. }
  264. }
  265. public static void main(String[] args) throws Exception {
  266. PaypalConfig paypalConfig = new PaypalConfig();
  267. paypalConfig.setBaseUrl("https://api-m.sandbox.paypal.com");
  268. paypalConfig.setClientId("ATzzbHdy4kgJxUJegzDbBO1kRUE5kcur5VXaNtja4JDpLsfPokdlKAtunTVa_mWPcTQTMy06JAW6Ae5j");
  269. paypalConfig.setSecret("EPBsjKmNHHrmu0joNkWcrVpdqXTs3pow5jRdD1daOMyomteOxHMUDXhsM6Z-bjMi8MfSMB4iIyuhIihV");
  270. try {
  271. Map<String,String> map = new HashMap<>(4);
  272. map.put("Content-Type","application/json");
  273. WebhookVo webhookVo = new WebhookVo();
  274. webhookVo.setUrl("https://testeur.4dkankan.com/service/pay/paypal/webhook");
  275. webhookVo.getEvent_types().add(new EventTypeVo("CATALOG.PRODUCT.CREATED"));
  276. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.CREATED"));
  277. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.ACTIVATED"));
  278. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.CREATED"));
  279. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.EXPIRED"));
  280. webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.SUSPENDED"));
  281. webhookVo.getEvent_types().add(new EventTypeVo("PAYMENT.SALE.COMPLETED"));
  282. String string = JSONObject.toJSONString(webhookVo);
  283. String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/notifications/webhooks")
  284. .addHeaders(map)
  285. .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret())
  286. .body(string)
  287. .execute().body();
  288. log.info("paypal-createWebhooks:{}",body);
  289. JSONObject resp = JSONObject.parseObject(body);
  290. String webhookId = resp.getString("id");
  291. paypalConfig.setWebhookId(webhookId);
  292. }catch (Exception e){
  293. log.info("paypal-createWebhooks:error:",e);
  294. }
  295. }
  296. }