マイクロチャネルの有料コールインターフェース(転送)

マイクロチャネルの有料コール・インタフェース

 免責事項:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/zoroduyu/article/details/79911278

先週のブログでは、私たちは少額決済インターフェイスの手紙を呼び出す方法について話していき今週、Alipayの支払インターフェースを呼び出すことについて話しました。 
話の前に与えられることにまだあるマイクロインタフェース記述の公式書簡を次のようにシーンの公式な説明は次のとおりです。

ここで説明する絵を書きます

実際には、PC-支払いのシナリオが類似している、ユーザーは、2次元コード、マイクロチャンネルスキャンコードの成功後に支払いを生成するためのボタンをクリックします。マイクロチャネルインターフェイスを呼び出すには、まず次のように、ジャーパッケージマイクロチャネルの賃金を導入する必要があります。

        <dependency>
            <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>0.0.3</version> </dependency>

 

 

私は、次のツールになった、マイクロチャネルの公式が変更ビットの例をもたらした呼び出します。

package com.example.ffmpeg;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.wxpay.sdk.WXPay; public class WXService { private static Logger logger = LoggerFactory.getLogger(WXService.class); private WXPay wxpay; private WXPayConfigImpl config; private static WXService INSTANCE; private WXService() throws Exception { config = WXPayConfigImpl.getInstance(); wxpay = new WXPay(config); } public static WXService getInstance() throws Exception { if (INSTANCE == null) { synchronized (WXPayConfigImpl.class) { if (INSTANCE == null) { INSTANCE = new WXService(); } } } return INSTANCE; } /** * 微信下單接口 * * @param out_trade_no * @param body * @param money * @param applyNo * @return */ public String doUnifiedOrder(String out_trade_no, String body, Double money, String applyNo) { String amt = String.valueOf(money * 100); HashMap<String, String> data = new HashMap<String, String>(); data.put("body", body); data.put("out_trade_no", out_trade_no); data.put("device_info", "web"); data.put("fee_type", "CNY"); data.put("total_fee", amt.substring(0, amt.lastIndexOf("."))); data.put("spbill_create_ip", config.getSpbillCreateIp()); data.put("notify_url", config.getNotifUrl()); data.put("trade_type", config.getTradeType()); data.put("product_id", applyNo); System.out.println(String.valueOf(money * 100)); // data.put("time_expire", "20170112104120"); try { Map<String, String> r = wxpay.unifiedOrder(data); logger.info("返回的参数是" + r); return r.get("code_url"); } catch (Exception e) { e.printStackTrace(); logger.info(e.getMessage()); return null; } } /** * 退款 已测试 */ public void doRefund(String out_trade_no, String total_fee) { logger.info("退款时的订单号为:" + out_trade_no + "退款时的金额为:" + total_fee); String amt = String.valueOf(Double.parseDouble(total_fee) * 100); logger.info("修正后的金额为:" + amt); logger.info("最终的金额为:" + amt.substring(0, amt.lastIndexOf("."))); HashMap<String, String> data = new HashMap<String, String>(); data.put("out_trade_no", out_trade_no); data.put("out_refund_no", out_trade_no); data.put("total_fee", amt.substring(0, amt.lastIndexOf("."))); data.put("refund_fee", amt.substring(0, amt.lastIndexOf("."))); data.put("refund_fee_type", "CNY"); data.put("op_user_id", config.getMchID()); try { Map<String, String> r = wxpay.refund(data); logger.info("退款操作返回的参数为" + r); } catch (Exception e) { e.printStackTrace(); } } /** * 微信验签接口 * * @param out_trade_no * @param body * @param money * @param applyNo * @return * @throws DocumentException */ public boolean checkSign(String strXML) throws DocumentException { SortedMap<String, String> smap = new TreeMap<String, String>(); Document doc = DocumentHelper.parseText(strXML); Element root = doc.getRootElement(); for (Iterator iterator = root.elementIterator(); iterator.hasNext();) { Element e = (Element) iterator.next(); smap.put(e.getName(), e.getText()); } return isWechatSign(smap,config.getKey()); } private boolean isWechatSign(SortedMap<String, String> smap,String apiKey) { StringBuffer sb = new StringBuffer(); Set<Entry<String, String>> es = smap.entrySet(); Iterator<Entry<String, String>> it = es.iterator(); while (it.hasNext()) { Entry<String, String> entry = it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if (!"sign".equals(k) && null != v && !"".equals(v) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + apiKey); /** 验证的签名 */ String sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase(); /** 微信端返回的合法签名 */ String validSign = ((String) smap.get("sign")).toUpperCase(); return validSign.equals(sign); } } 

 

私は、クラス内部の包装WXServiceツールの動作を確認するために、マイクロチャネル、払い戻し、検査単一。このクラスは、2つのメンバ変数とwxpayの設定を必要とする対象WXPayとWXPayConfigImplの例です。WXPayマイクロメッセージは、キットからの引用です。WXPayConfigImplそれは次のように、クラスを作成することです:

package com.example.ffmpeg;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream; import com.github.wxpay.sdk.WXPayConfig; public class WXPayConfigImpl implements WXPayConfig{ private byte[] certData; private static WXPayConfigImpl INSTANCE; private WXPayConfigImpl() throws Exception{ String certPath = "F:\\weixin\\apiclient_cert.p12"; File file = new File(certPath); InputStream certStream = new FileInputStream(file); this.certData = new byte[(int) file.length()]; certStream.read(this.certData); certStream.close(); } public static WXPayConfigImpl getInstance() throws Exception{ if (INSTANCE == null) { synchronized (WXPayConfigImpl.class) { if (INSTANCE == null) { INSTANCE = new WXPayConfigImpl(); } } } return INSTANCE; } public String getAppID() { return "你的appid"; } public String getMchID() { return "你的商户id"; } public String getKey() { return "你设置的key值"; } public String getNotifUrl() { return "微信通知回调的url接口"; } public String getTradeType() { return "NATIVE"; } public InputStream getCertStream() { ByteArrayInputStream certBis; certBis = new ByteArrayInputStream(this.certData); return certBis; } public int getHttpConnectTimeoutMs() { return 2000; } public int getHttpReadTimeoutMs() { return 10000; } // IWXPayDomain getWXPayDomain() { // return WXPayDomainSimpleImpl.instance(); // } public String getPrimaryDomain() { return "api.mch.weixin.qq.com"; } public String getAlternateDomain() { return "api2.mch.weixin.qq.com"; } public int getReportWorkerNum() { return 1; } public int getReportBatchSize() { return 2; } public String getSpbillCreateIp() { // TODO Auto-generated method stub return "192.168.1.1"; } }

 

このクラスはWXPayConfigは、主にマイクロチャネルをインタフェースするために必要なパラメータを返す、いくつかの方法をカプセル化するマイクロチャネルを、提供されるインターフェースを実装していることが分かります。この証明書ファイルは、のapiclient_cert.p12という名前のファイルを読むために必要があることは注目に値します。ログオンできる証明書ファイル商人プラットフォームマイクロ手紙ここでは、必要な証明書をダウンロードします。コンストラクタの内部WXPayConfigImplファイルを読み、そのコンストラクタが例外をスローします。コンストラクタが例外をスローするので、代わりに単一の実施形態を実現するために二重ロック方式を使用してのない内部の静的クラスオブジェクトが存在しないからです。

回到WXService这个类中,代码往下走,在WXService的构造器中对config和wxpay进行了实例化。接下来同样是用双检锁的方式实现的单例。往下走,微信的下单接口,分别传入out_trade_no(外部订单号),body(商品描述), money(付款金额), applyNo(对应微信的product_id:商品id,由商户自定义)四个参数。进入方法后第一句话String amt = String.valueOf(money * 100);是把传入的钱数乘以100,并转换成字符串。这里之所以乘以100是因为微信那边会把我们传过去的钱数除以100得到应付金额,且不能传小数,所以下面的那一句amt.substring(0, amt.lastIndexOf(“.”))就是为了把金额中的小数点去掉。往下走,new出了一个hashmap,将参数传入hashmap中,然后调用wxpay.unifiedOrder(data);下单接口下单。得到返回的map集合,从map中获得的code_url这个参数就是微信返回给我们生成二维码的字符串。这样,下单的整个流程就跑通了,现在写个测试类来测试一下。

package com.example.ffmpeg;

public class Test {

    public static void main(String[] args) throws Exception { WXService wx = WXService.getInstance(); String QRcode = wx.doUnifiedOrder("test001", "测试下单接口", 0.01, "a123456"); System.out.println("得到的二维码是:"+QRcode); } }

 

运行结果如下图:

ここで説明する絵を書きます

如何检验该二维码是否是正确的喃?很简单,打开百度,搜索二维码生成器,如下图所示:

ここで説明する絵を書きます

点击进入第二个百度应用里面的进入应用,出现如下图所示:

ここで説明する絵を書きます

选择通用文本,在中间的文本框中粘贴刚才拿到的二维码字符串,点击生成按钮,右边就会生成一个二维码了。如下:

ここで説明する絵を書きます

当然,这只是我们后台人员测试时使用的方法,实际生产环境中前端可以用一些javascript的插件去生成二维码。

下单接口完了之后,紧接着就是退款的方法,该方法比较简单且和下单方法大同小异,同学们自己看看注释应该可以理解了。再往后走是微信验签的方法。在讲这个方法之前,先来看看微信的回调方法:

/**
     * 微信回调的接口
     * 
     * @param uuid
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/wxReturnPay")
    public void wxReturnPay(HttpServletResponse response, HttpServletRequest request)
            throws Exception {

        logger.info("****************************************wxReturnPay微信的回调函数被调用******************************"); String inputLine; String notityXml = ""; request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.setHeader("Access-Control-Allow-Origin", "*"); // 微信给返回的东西 try { while ((inputLine = request.getReader().readLine()) != null) { notityXml += inputLine; } request.getReader().close(); } catch (Exception e) { e.printStackTrace(); logger.info("xml获取失败"); response.getWriter().write(setXml("fail", "xml获取失败")); return; } if (StringUtils.isEmpty(notityXml)) { logger.info("xml为空"); response.getWriter().write(setXml("fail", "xml为空")); return; } WXService wxService = WXService.getInstance(); if(!wxService.checkSign(notityXml)) { response.getWriter().write(setXml("fail", "验签失败")); } logger.info("xml的值为:" + notityXml); XMLSerializer xmlSerializer = new XMLSerializer(); JSON json = xmlSerializer.read(notityXml); logger.info(json.toString()); JSONObject jsonObject=JSONObject.fromObject(json.toString()); UnifiedOrderRespose returnPay = (UnifiedOrderRespose) JSONObject.toBean(jsonObject, UnifiedOrderRespose.class); logger.info(("转换后的实体bean为:"+returnPay.toString())); logger.info(("订单号:"+returnPay.getOut_trade_no()+"价格:"+returnPay.getTotal_fee())); if (returnPay.getReturn_code().equals("SUCCESS") && returnPay.getOut_trade_no() != null && !returnPay.getOut_trade_no().isEmpty()) { double fee = Double.parseDouble(returnPay.getTotal_fee()); returnPay.setTotal_fee(String.valueOf(fee/100)); logger.info("微信的支付状态为SUCCESS"); tbPaymentRecordsService.wxPaySuccess(returnPay); } }

 

成功入金後、マイクロチャネルは、(私たちは、インターフェイスに単一の呼び出しの下を通過するときのコールバックURLが過去である)コールバックメソッドになります。入力方法、オブジェクトの最初のインスタンスが、彼は、XML形式の文字列が文字列であるマイクロチャネルが読み出さnotityXml結果がある、読み出され、コールバックパラメータの各種情報が存在するのHttpServletRequestストリームを取得する、例では、結果を返します次のように:

<xml>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid> <attach><![CDATA[支付测试]]></attach> <bank_type><![CDATA[CFT]]></bank_type> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str> <openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid> <out_trade_no><![CDATA[1409811653]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign> <sub_mch_id><![CDATA[10000100]]></sub_mch_id> <time_end><![CDATA[20140903131540]]></time_end> <total_fee>1</total_fee> <coupon_fee><![CDATA[10]]></coupon_fee> <coupon_count><![CDATA[1]]></coupon_count> <coupon_type><![CDATA[CASH]]></coupon_type> <coupon_id><![CDATA[10000]]></coupon_id> <coupon_fee><![CDATA[100]]></coupon_fee> <trade_type><![CDATA[JSAPI]]></trade_type> <transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id> </xml> 

引数が背後にある。このような自然にXML解析パラメータを含むことである返します。経験への看板の方法:

/**
     * 微信验签接口
     * 
     * @param out_trade_no
     * @param body
     * @param money
     * @param applyNo * @return * @throws DocumentException */ public boolean checkSign(String strXML) throws DocumentException { SortedMap<String, String> smap = new TreeMap<String, String>(); Document doc = DocumentHelper.parseText(strXML); Element root = doc.getRootElement(); for (Iterator iterator = root.elementIterator(); iterator.hasNext();) { Element e = (Element) iterator.next(); smap.put(e.getName(), e.getText()); } return isWechatSign(smap,config.getKey()); } private boolean isWechatSign(SortedMap<String, String> smap,String apiKey) { StringBuffer sb = new StringBuffer(); Set<Entry<String, String>> es = smap.entrySet(); Iterator<Entry<String, String>> it = es.iterator(); while (it.hasNext()) { Entry<String, String> entry = it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if (!"sign".equals(k) && null != v && !"".equals(v) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + apiKey); /** 验证的签名 */ String sign = MD5Util.MD5Encode(sb.toString(), "utf-8").toUpperCase(); /** 微信端返回的合法签名 */ String validSign = ((String) smap.get("sign")).toUpperCase(); return validSign.equals(sign); }

 

最初の結果の文字列解析DocumentオブジェクトとDOM4J DocumentHelper、次いで要素を用いて得られた物体、トラバーサル、キーと値のSortedMapに格納され、その後のSortedMapで使用される方法と言えば、マイクロisWechatSign方法のSortedMap文字キーと一緒に渡された値反復、KEY1 =値1&KEY2 =ような形態の値2ステッチキーと値、スプライシングおよび以下の点に注意してください。

◆昇順でASCIIコードパラメータ名(辞書式); 
◆パラメータは署名ヌルに関与していない場合、 
◆パラメータ名は、大文字と小文字が区別され、 
それが返すか確認◆マイクロチャネル事前通知シグネチャ場合、送信されたパラメータに関与しない署名の署名生成された署名値とチェックのサイン。 
◆マイクロチャネルインタフェースがフィールドを増加させることができる、署名検証中に増加拡張フィールドをサポートするために必要です

MD5を使用して暗号化済み文字列の連結後、次いで得られた文字列がすべて大文字に変換されます。変換後の文字列が同じ場合は同じではありません、そして、チェックが検査に合格しなかった場合、符号検定は、成功すると、比較のために、当社のマイクロ文字の符号パラメータを渡します。

検証メソッドのシグネチャは、ビジネスロジックのカテゴリに属した後、ビジネス・ロジックは、誰にとっても同じではありません、と私はここでそれらを繰り返すことはしません。だから、これは私の見ることができますAlipayの学生を呼び出す方法を見て、私は終わっていたマイクロチャネルの基本的な操作と呼ばれているのAlipayの呼び出しインタフェースこの記事を。そして、ここで、このブログ、さようなら。

おすすめ

転載: www.cnblogs.com/LiZhongZhongY/p/10992552.html