/* * Copyright 2015 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon.rnsd.service.handler; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Resource; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.ParseException; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.skfiy.typhon.rnsd.domain.Platform; import org.skfiy.typhon.rnsd.domain.Recharging; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class AppleRechargingHandler implements RechargingHandler { private static final Logger LOG = LoggerFactory.getLogger(AppleRechargingHandler.class); private static final String SANDBOX_URL = "https://sandbox.itunes.apple.com/verifyReceipt"; private static final String VERIFY_URL = "https://buy.itunes.apple.com/verifyReceipt"; private final HttpClientBuilder HC_BUILDER = HttpClientBuilder.create(); private final Pattern P = Pattern.compile("(\"signature\" = \"(.*?)\";)"); @Resource private Map<String, Integer> goodsPrices; public AppleRechargingHandler() throws Exception { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); HC_BUILDER.setSslcontext(sc); } @Override public RechargingBO handle(JSONObject json) throws TradeValidatedException { String uri; if ("Sandbox".equalsIgnoreCase(json.getString("environment"))) { uri = SANDBOX_URL; } else { uri = VERIFY_URL; } CloseableHttpClient hc = HC_BUILDER.build(); HttpPost post = new HttpPost(uri); List<NameValuePair> nvps = new ArrayList<>(); String receiptStr = json.getString("data"); Matcher m = P.matcher(receiptStr); m.find(); String signature = m.group(2).replaceAll(" ", "+"); receiptStr = receiptStr.replace(m.group(2), signature); String receiptData = org.skfiy.typhon.rnsd.Base64.encodeBytes(receiptStr.getBytes()); JSONObject receiptJson = new JSONObject(); receiptJson.put("receipt-data", receiptData); try { post.setEntity(new StringEntity(receiptJson.toJSONString(), ContentType.APPLICATION_JSON)); CloseableHttpResponse resp = hc.execute(post); String str = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8); JSONObject result = JSON.parseObject(str); if (result.getIntValue("status") != 0) { throw new TradeValidatedException("success", "no verify"); } JSONObject receipt = result.getJSONObject("receipt"); // result Recharging recharging = new Recharging(); recharging.setTradeId(receipt.getString("transaction_id")); recharging.setPlatform(Platform.apple.getLabel()); String callbackInfo = StringUtils.newStringUtf8(Base64.decodeBase64(json.getString("callbackInfo"))); JSONObject extra = JSON.parseObject(callbackInfo); recharging.setUid(extra.getString("uid")); recharging.setRegion(extra.getString("region")); recharging.setGoods(extra.getString("goods")); LOG.debug("{}", extra); recharging.setAmount(extra.getInteger("goods")); recharging.setCreationTime(System.currentTimeMillis() / 1000); recharging.setChannel(Platform.apple.getLabel()); return (new RechargingBO(recharging, "success")); } catch (Exception ex) { throw new TradeValidatedException("success", ex.getMessage()); } finally { try { hc.close(); } catch (IOException ex) { } } } private static class TrustAnyTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } private static class TrustAnyHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { return true; } } }