package com.fdkankan.pay.util.paypal.restApi; import cn.hutool.http.Header; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fdkankan.pay.entity.PaypalConfig; import com.fdkankan.pay.service.IPaypalConfigService; import com.fdkankan.pay.util.CacheUtil; import com.fdkankan.pay.util.paypal.restApi.vo.EventTypeVo; import com.fdkankan.pay.util.paypal.restApi.vo.Product; import com.fdkankan.pay.util.paypal.restApi.vo.WebhookVo; import com.fdkankan.pay.util.paypal.restApi.vo.plan.*; import com.fdkankan.pay.util.paypal.restApi.vo.subscription.*; import com.paypal.api.payments.EventType; import com.paypal.api.payments.Links; import com.paypal.api.payments.Webhook; import com.paypal.api.payments.WebhookList; import com.paypal.base.rest.APIContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.time.*; import java.util.*; @Service @Slf4j public class RestApiPaypalService { @Autowired IPaypalConfigService paypalConfigService; /** * 启动创建webhooks * https://testeur.4dkankan.com/service/pay/paypal/webhook */ @PostConstruct public void createWebhooks() { log.info("--------------项目启动初始化webhook-------------"); List list = paypalConfigService.list(); for (PaypalConfig paypalConfig : list) { if(StringUtils.isBlank(paypalConfig.getWebhookId())){ try { Map map = new HashMap<>(4); map.put("Content-Type","application/json"); WebhookVo webhookVo = new WebhookVo(); webhookVo.setUrl(paypalConfig.getWebhookHost() +"/service/pay/paypal/webhook"); webhookVo.getEvent_types().add(new EventTypeVo("CATALOG.PRODUCT.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.ACTIVATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.EXPIRED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.SUSPENDED")); webhookVo.getEvent_types().add(new EventTypeVo("PAYMENT.SALE.COMPLETED")); String string = JSONObject.toJSONString(webhookVo); String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/notifications/webhooks") .addHeaders(map) .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret()) .body(string) .execute().body(); log.info("paypal-createWebhooks:{}",body); JSONObject resp = JSONObject.parseObject(body); String webhookId = resp.getString("id"); paypalConfig.setWebhookId(webhookId); LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(PaypalConfig::getId,paypalConfig.getId()); wrapper.set(PaypalConfig::getWebhookId,webhookId); paypalConfigService.update(wrapper); }catch (Exception e){ log.info("paypal-createWebhooks:error:",e); } } } } /** * 获取token */ public static String getToken(PaypalConfig paypalConfig) { String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/oauth2/token") .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret()) .form("grant_type", "client_credentials") .execute().body(); JSONObject jsonObject = JSONObject.parseObject(body); return jsonObject.get("access_token").toString(); } /** * 创建商品 */ public String createProduct(PaypalConfig paypalConfig,Product product) { try { Map map = new HashMap<>(4); map.put("Content-Type","application/json"); map.put("Authorization",getToken(paypalConfig)); // map.put("PayPal-Request-Id","PLAN-18062019-001"); String string = new ObjectMapper().writeValueAsString(product); String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/catalogs/products") .addHeaders(map) .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret()) .body(string) .execute().body(); log.info("paypal-createProduct:{}",body); JSONObject jsonObject = JSONObject.parseObject(body); return jsonObject.getString("id"); }catch (Exception e){ log.info("paypal-createProduct:error:",e); } return null; } /** * 创建计划 * */ public String createPlan(PaypalConfig paypalConfig,PlanVo planVo) { try { String dateTime = LocalDateTime.now().toString(); Map map = new HashMap<>(4); map.put("Content-Type","application/json"); map.put("Authorization",getToken(paypalConfig)); // map.put("PayPal-Request-Id","PLAN-18062019-001"); PayPalSubscriptionPlanParam planParam = new PayPalSubscriptionPlanParam(); List list = new ArrayList<>(); BillingCycles billingCycles = new BillingCycles(); billingCycles.setTenureType("REGULAR"); billingCycles.setSequence(1); billingCycles.setTotalCycles(0); //计费周期 Frequency frequency = new Frequency(); frequency.setIntervalUnit(planVo.getTimeUnit()); frequency.setIntervalCount(1); PricingScheme pricingScheme = new PricingScheme(); pricingScheme.setVersion(1); pricingScheme.setCreateTime(dateTime); //定价 FixedPrice fixedPrice = new FixedPrice(); fixedPrice.setCurrencyCode(planVo.getCurrencyCode()); fixedPrice.setValue(planVo.getPrice()); pricingScheme.setFixedPrice(fixedPrice); billingCycles.setFrequency(frequency); billingCycles.setPricingScheme(pricingScheme); list.add(billingCycles); // 付款偏好 PaymentPreferences paymentPreferences = new PaymentPreferences(); paymentPreferences.setAutoBillOutstanding(true); paymentPreferences.setPaymentFailureThreshold(3); paymentPreferences.setSetupFeeFailureAction("CANCEL"); SetupFee setupFee = new SetupFee(); setupFee.setCurrencyCode(planVo.getCurrencyCode()); setupFee.setValue("0"); paymentPreferences.setSetupFee(setupFee); // 税率 Taxes taxes = new Taxes(); taxes.setInclusive(true); taxes.setPercentage("0"); planParam.setTaxes(taxes); planParam.setPaymentPreferences(paymentPreferences); planParam.setBillingCycles(list); planParam.setProductId(planVo.getProductId()); planParam.setName(planVo.getPlanName()); planParam.setStatus("ACTIVE"); planParam.setDescription(planVo.getPlanName()); planParam.setCreateTime(dateTime); planParam.setUpdateTime(dateTime); String string = new ObjectMapper().writeValueAsString(planParam); String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/plans") .addHeaders(map) .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret()) .body(string) .execute().body(); log.info("paypal-createPlan:{}",body); JSONObject planObj = JSONObject.parseObject(body); return planObj.getString("id"); }catch (Exception e){ log.info("paypal-createPlan:error:",e); } return null; } /** * 处理订阅参数 * * @param planId * @return */ private String handlerSubsParam(String planId,ApplicationContext applicationContext) { CompanyVo companyVo = new CompanyVo(); SubscriptionDTO subscriptionDTO = new SubscriptionDTO(); subscriptionDTO.setPlanId(planId); // subscriptionDTO.setQuantity("10"); // subscriptionDTO.setShippingAmount("10"); // subscriptionDTO.setStartTime(new Date()); // subscriptionDTO.setQuantity("10"); Subscriber subscriber = new Subscriber(); SubscriberName subscriberName = new SubscriberName(); subscriberName.setGiven_name(companyVo.getName()); subscriberName.setSurname(companyVo.getName()); subscriber.setName(subscriberName); subscriber.setEmailAddress(companyVo.getEmail()); ShippingAddress shippingAddress = new ShippingAddress(); shippingAddress.setAddress(new Address(companyVo.getAddress(),"","","","","C2")); shippingAddress.setName(new Name(companyVo.getName())); subscriber.setShippingAddress(shippingAddress); subscriptionDTO.setSubscriber(subscriber); subscriptionDTO.setApplicationContext(applicationContext); String string = ""; try { string = new ObjectMapper().writeValueAsString(subscriptionDTO); // System.out.println(string); } catch (JsonProcessingException e) { e.printStackTrace(); } return string; } /** * 创建订阅 */ public SubscriptionVo createSubscription(PaypalConfig paypalConfig,String planId) { Map map = new HashMap<>(4); map.put("Content-Type","application/json"); map.put("Authorization",getToken(paypalConfig)); // P-7EG815794T029494CMFR77TA // String planId = "P-4ND94871NA4029913MFSTSXI"; ApplicationContext applicationContext = new ApplicationContext(); applicationContext.setCancelUrl(paypalConfig.getCancelUrl()); applicationContext.setReturnUrl(paypalConfig.getSuccessUrl()); applicationContext.setPaymentMethod(new PaymentMethod()); String string = handlerSubsParam(planId,applicationContext); String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/subscriptions") .addHeaders(map) .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret()) .body(string) .execute().body(); JSONObject jsonObject = JSONObject.parseObject(body); log.info("createSubscription-resp:{}",jsonObject); String id = jsonObject.getString("id"); List links = JSONObject.parseArray(jsonObject.get("links").toString(), com.paypal.api.payments.Links.class); Links links1 = links.stream().filter(o -> "approve".equals(o.getRel())).findFirst() .orElseThrow(() -> new RuntimeException("创建订阅失败")); String href = links1.getHref(); SubscriptionVo vo = new SubscriptionVo(id, href); return vo; } /** * 取消订阅 */ public void cancelSubscriptions(PaypalConfig paypalConfig, String subscriptionsId) { Map map = new HashMap<>(4); map.put("Content-Type","application/json"); map.put("Authorization",getToken(paypalConfig)); HttpResponse response = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/billing/subscriptions/"+subscriptionsId+"/cancel") .addHeaders(map) .basicAuth(paypalConfig.getClientId(),paypalConfig.getSecret()) .execute(); // 订阅正常创建 log.info("resp:{}",response); if (response.getStatus() == 201) { JSONObject respObj = JSONObject.parseObject(response.body()); System.out.println(respObj); } } public static void main(String[] args) throws Exception { PaypalConfig paypalConfig = new PaypalConfig(); paypalConfig.setBaseUrl("https://api-m.sandbox.paypal.com"); paypalConfig.setClientId("ATzzbHdy4kgJxUJegzDbBO1kRUE5kcur5VXaNtja4JDpLsfPokdlKAtunTVa_mWPcTQTMy06JAW6Ae5j"); paypalConfig.setSecret("EPBsjKmNHHrmu0joNkWcrVpdqXTs3pow5jRdD1daOMyomteOxHMUDXhsM6Z-bjMi8MfSMB4iIyuhIihV"); try { Map map = new HashMap<>(4); map.put("Content-Type","application/json"); WebhookVo webhookVo = new WebhookVo(); webhookVo.setUrl("https://testeur.4dkankan.com/service/pay/paypal/webhook"); webhookVo.getEvent_types().add(new EventTypeVo("CATALOG.PRODUCT.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.PLAN.ACTIVATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.CREATED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.EXPIRED")); webhookVo.getEvent_types().add(new EventTypeVo("BILLING.SUBSCRIPTION.SUSPENDED")); webhookVo.getEvent_types().add(new EventTypeVo("PAYMENT.SALE.COMPLETED")); String string = JSONObject.toJSONString(webhookVo); String body = HttpRequest.post(paypalConfig.getBaseUrl() + "/v1/notifications/webhooks") .addHeaders(map) .basicAuth(paypalConfig.getClientId(), paypalConfig.getSecret()) .body(string) .execute().body(); log.info("paypal-createWebhooks:{}",body); JSONObject resp = JSONObject.parseObject(body); String webhookId = resp.getString("id"); paypalConfig.setWebhookId(webhookId); }catch (Exception e){ log.info("paypal-createWebhooks:error:",e); } } }