|
6 | 6 | import com.google.gson.internal.Streams;
|
7 | 7 | import com.google.gson.reflect.TypeToken;
|
8 | 8 | import com.google.gson.stream.JsonReader;
|
| 9 | +import com.thoughtworks.xstream.XStream; |
9 | 10 | import me.chanjar.weixin.common.bean.WxAccessToken;
|
10 | 11 | import me.chanjar.weixin.common.bean.WxMenu;
|
11 | 12 | import me.chanjar.weixin.common.bean.WxJsapiSignature;
|
|
17 | 18 | import me.chanjar.weixin.common.util.RandomUtils;
|
18 | 19 | import me.chanjar.weixin.common.util.StringUtils;
|
19 | 20 | import me.chanjar.weixin.common.util.crypto.SHA1;
|
| 21 | +import me.chanjar.weixin.common.util.crypto.WxCryptUtil; |
20 | 22 | import me.chanjar.weixin.common.util.fs.FileUtils;
|
21 | 23 | import me.chanjar.weixin.common.util.http.*;
|
22 | 24 | import me.chanjar.weixin.common.util.json.GsonHelper;
|
| 25 | +import me.chanjar.weixin.common.util.xml.XStreamInitializer; |
23 | 26 | import me.chanjar.weixin.mp.bean.*;
|
24 | 27 | import me.chanjar.weixin.mp.bean.result.*;
|
25 | 28 | import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor;
|
26 | 29 | import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
|
| 30 | +import org.apache.http.Consts; |
27 | 31 | import org.apache.http.HttpHost;
|
28 | 32 | import org.apache.http.auth.AuthScope;
|
29 | 33 | import org.apache.http.auth.UsernamePasswordCredentials;
|
|
32 | 36 | import org.apache.http.client.config.RequestConfig;
|
33 | 37 | import org.apache.http.client.methods.CloseableHttpResponse;
|
34 | 38 | import org.apache.http.client.methods.HttpGet;
|
| 39 | +import org.apache.http.client.methods.HttpPost; |
| 40 | +import org.apache.http.entity.StringEntity; |
35 | 41 | import org.apache.http.impl.client.BasicCredentialsProvider;
|
36 | 42 | import org.apache.http.impl.client.BasicResponseHandler;
|
37 | 43 | import org.apache.http.impl.client.CloseableHttpClient;
|
|
43 | 49 | import java.io.IOException;
|
44 | 50 | import java.io.InputStream;
|
45 | 51 | import java.io.StringReader;
|
| 52 | +import java.math.BigDecimal; |
46 | 53 | import java.security.NoSuchAlgorithmException;
|
47 |
| -import java.util.Date; |
48 |
| -import java.util.List; |
49 |
| -import java.util.UUID; |
| 54 | +import java.util.*; |
50 | 55 |
|
51 | 56 | public class WxMpServiceImpl implements WxMpService {
|
52 | 57 |
|
@@ -332,6 +337,19 @@ public WxMpQrCodeTicket qrCodeCreateLastTicket(int scene_id) throws WxErrorExcep
|
332 | 337 | String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString());
|
333 | 338 | return WxMpQrCodeTicket.fromJson(responseContent);
|
334 | 339 | }
|
| 340 | + |
| 341 | + public WxMpQrCodeTicket qrCodeCreateLastTicket(String scene_str) throws WxErrorException { |
| 342 | + String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create"; |
| 343 | + JsonObject json = new JsonObject(); |
| 344 | + json.addProperty("action_name", "QR_LIMIT_STR_SCENE"); |
| 345 | + JsonObject actionInfo = new JsonObject(); |
| 346 | + JsonObject scene = new JsonObject(); |
| 347 | + scene.addProperty("scene_str", scene_str); |
| 348 | + actionInfo.add("scene", scene); |
| 349 | + json.add("action_info", actionInfo); |
| 350 | + String responseContent = execute(new SimplePostRequestExecutor(), url, json.toString()); |
| 351 | + return WxMpQrCodeTicket.fromJson(responseContent); |
| 352 | + } |
335 | 353 |
|
336 | 354 | public File qrCodePicture(WxMpQrCodeTicket ticket) throws WxErrorException {
|
337 | 355 | String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode";
|
@@ -613,4 +631,77 @@ public void setMaxRetryTimes(int maxRetryTimes) {
|
613 | 631 | this.maxRetryTimes = maxRetryTimes;
|
614 | 632 | }
|
615 | 633 |
|
| 634 | + @Override |
| 635 | + public WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl) { |
| 636 | + String nonce_str = System.currentTimeMillis() + ""; |
| 637 | + |
| 638 | + SortedMap<String, String> packageParams = new TreeMap<String, String>(); |
| 639 | + packageParams.put("appid", wxMpConfigStorage.getAppId()); |
| 640 | + packageParams.put("mch_id", wxMpConfigStorage.getPartnerId()); |
| 641 | + packageParams.put("nonce_str", nonce_str); |
| 642 | + packageParams.put("body", body); |
| 643 | + packageParams.put("out_trade_no", outTradeNo); |
| 644 | + |
| 645 | + packageParams.put("total_fee", (int)(amt*100) + ""); |
| 646 | + packageParams.put("spbill_create_ip", ip); |
| 647 | + packageParams.put("notify_url", callbackUrl); |
| 648 | + packageParams.put("trade_type", tradeType); |
| 649 | + packageParams.put("openid", openId); |
| 650 | + |
| 651 | + String sign = WxCryptUtil.createSign(packageParams, wxMpConfigStorage.getPartnerKey()); |
| 652 | + String xml = "<xml>" + |
| 653 | + "<appid>" + wxMpConfigStorage.getAppId() + "</appid>" + |
| 654 | + "<mch_id>" + wxMpConfigStorage.getPartnerId() + "</mch_id>" + |
| 655 | + "<nonce_str>" + nonce_str + "</nonce_str>" + |
| 656 | + "<sign>" + sign + "</sign>" + |
| 657 | + "<body><![CDATA[" + body + "]]></body>" + |
| 658 | + "<out_trade_no>" + outTradeNo + "</out_trade_no>" + |
| 659 | + "<total_fee>" + packageParams.get("total_fee") + "</total_fee>" + |
| 660 | + "<spbill_create_ip>" + ip + "</spbill_create_ip>" + |
| 661 | + "<notify_url>" + callbackUrl + "</notify_url>" + |
| 662 | + "<trade_type>" + tradeType + "</trade_type>" + |
| 663 | + "<openid>" + openId + "</openid>" + |
| 664 | + "</xml>"; |
| 665 | + |
| 666 | + HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder"); |
| 667 | + if (httpProxy != null) { |
| 668 | + RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build(); |
| 669 | + httpPost.setConfig(config); |
| 670 | + } |
| 671 | + |
| 672 | + StringEntity entity = new StringEntity(xml, Consts.UTF_8); |
| 673 | + httpPost.setEntity(entity); |
| 674 | + try { |
| 675 | + CloseableHttpResponse response = httpClient.execute(httpPost); |
| 676 | + String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); |
| 677 | + XStream xstream = XStreamInitializer.getInstance(); |
| 678 | + xstream.alias("xml", WxMpPrepayIdResult.class); |
| 679 | + WxMpPrepayIdResult wxMpPrepayIdResult = (WxMpPrepayIdResult) xstream.fromXML(responseContent); |
| 680 | + return wxMpPrepayIdResult; |
| 681 | + } catch (IOException e) { |
| 682 | + e.printStackTrace(); |
| 683 | + } |
| 684 | + return new WxMpPrepayIdResult(); |
| 685 | + } |
| 686 | + |
| 687 | + @Override |
| 688 | + public Map<String, String> getJSSDKPayInfo(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String callbackUrl) { |
| 689 | + WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(openId, outTradeNo, amt, body, tradeType, ip, callbackUrl); |
| 690 | + String prepayId = wxMpPrepayIdResult.getPrepay_id(); |
| 691 | + if (prepayId == null || prepayId.equals("")) { |
| 692 | + throw new RuntimeException("get prepayid error"); |
| 693 | + } |
| 694 | + |
| 695 | + Map<String, String> payInfo = new HashMap<String, String>(); |
| 696 | + payInfo.put("appId", wxMpConfigStorage.getAppId()); |
| 697 | + // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 |
| 698 | + payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); |
| 699 | + payInfo.put("nonceStr", System.currentTimeMillis() + ""); |
| 700 | + payInfo.put("package", "prepay_id=" + prepayId); |
| 701 | + payInfo.put("signType", "MD5"); |
| 702 | + |
| 703 | + String finalSign = WxCryptUtil.createSign(payInfo, wxMpConfigStorage.getPartnerKey()); |
| 704 | + payInfo.put("sign", finalSign); |
| 705 | + return payInfo; |
| 706 | + } |
616 | 707 | }
|
0 commit comments