亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                微信支付后端篇

                微信支付系列文章

                微信支付-java后端實(shí)現(xiàn)

                微信支付-vue 前端實(shí)現(xiàn)

                java demo: 下載地址文章底部

                技術(shù)棧

                Spring boot

                java

                XML (微信在http協(xié)議中數(shù)據(jù)傳輸方案)

                MD5 簽名

                微信支付術(shù)語

                openid (OpenID是公眾號一對一對應(yīng)用戶身份的標(biāo)識)

                app_id (公眾號id,登錄微信公眾號–開發(fā)–基本配置中獲得;)

                key (收款商戶后臺進(jìn)行配置,登錄微信商戶平臺–賬戶中心–API安全-設(shè)置秘鑰,設(shè)置32位key值;)

                mch_id (收款商家商戶號;)

                certPath (API證書, 登錄微信商戶平臺–賬戶中心-API安全-下載證書)

                后端流程

                服務(wù)端需要的核心操作, 總共分為以下幾步:

                統(tǒng)一下單

                前端調(diào)起微信支付必要參數(shù) (需加密)

                訂單結(jié)果主動通知 (回調(diào)接口)

                查詢訂單結(jié)果

                結(jié)束訂單支付接口(關(guān)閉訂單,支付訂單關(guān)閉)

                代碼

                微信總共支持多種語言的sdk, 在官網(wǎng)可以下載例子, java程序也可以引入微信支付的sdk包, 但是github上的sdk已經(jīng)很久沒有更新了, 最好的選擇, 也是我的選擇, 在官網(wǎng)上下載sdk項(xiàng)目, 將其中所有java類copy到自己的項(xiàng)目中.

                官網(wǎng)sdk下載目錄

                鏈接: 商戶平臺首頁

                #### 根據(jù)微信sdk生成配置類 WXPayConfig

                創(chuàng)建IWxPayConfig.class, 繼承sdk WXPayConfig.class, 實(shí)現(xiàn)sdk中部分抽象方法, 讀取本地證書, 加載到配置類中.

                package core.com.chidori.wxpay;

                import core.com.wxpay.IWXPayDomain;

                import core.com.wxpay.WXPayConfig;

                import core.com.wxpay.WXPayConstants;

                import org.springframework.beans.factory.annotation.Value;

                import org.springframework.stereotype.Service;

                import java.io.ByteArrayInputStream;

                import java.io.File;

                import java.io.FileInputStream;

                import java.io.InputStream;

                @Service

                public class IWxPayConfig extends WXPayConfig { // 繼承sdk WXPayConfig 實(shí)現(xiàn)sdk中部分抽象方法

                private byte[] certData;

                @Value(“${vendor.wx.config.app_id}”)

                private String app_id;

                @Value(“${vendor.wx.pay.key}”)

                private String wx_pay_key;

                @Value(“${vendor.wx.pay.mch_id}”)

                private String wx_pay_mch_id;

                public IWxPayConfig() throws Exception { // 構(gòu)造方法讀取證書, 通過getCertStream 可以使sdk獲取到證書

                String certPath = “/data/config/chidori/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();

                }

                @Override

                public String getAppID() {

                return app_id;

                }

                @Override

                public String getMchID() {

                return wx_pay_mch_id;

                }

                @Override

                public String getKey() {

                return wx_pay_key;

                }

                @Override

                public InputStream getCertStream() {

                return new ByteArrayInputStream(this.certData);

                }

                @Override

                public IWXPayDomain getWXPayDomain() { // 這個方法需要這樣實(shí)現(xiàn), 否則無法正常初始化WXPay

                IWXPayDomain iwxPayDomain = new IWXPayDomain() {

                @Override

                public void report(String domain, long elapsedTimeMillis, Exception ex) {

                }

                @Override

                public DomainInfo getDomain(WXPayConfig config) {

                return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);

                }

                };

                return iwxPayDomain;

                }

                }

                發(fā)起統(tǒng)一下單 AND 前端調(diào)起微信支付必要參數(shù)

                // 發(fā)起微信支付

                WXPay wxpay = null;

                Map result = new HashMap();

                try {

                // ******************************************

                //

                // 統(tǒng)一下單

                //

                // ******************************************

                wxpay = new WXPay(iWxPayConfig); // *** 注入自己實(shí)現(xiàn)的微信配置類, 創(chuàng)建WXPay核心類, WXPay 包括統(tǒng)一下單接口

                Map data = new HashMap();

                data.put(“body”, “訂單詳情”);

                data.put(“out_trade_no”, transOrder.getGlobalOrderId()); // 訂單唯一編號, 不允許重復(fù)

                data.put(“total_fee”, String.valueOf(transOrder.getOrderAmount().multiply(new BigDecimal(100)).intValue())); // 訂單金額, 單位分

                data.put(“spbill_create_ip”, “192.168.31.166”); // 下單ip

                data.put(“openid”, openId); // 微信公眾號統(tǒng)一標(biāo)示openid

                data.put(“notify_url”, “http://wxlj.oopmind.com/payCallback”); // 訂單結(jié)果通知, 微信主動回調(diào)此接口

                data.put(“trade_type”, “JSAPI”); // 固定填寫

                logger.info(“發(fā)起微信支付下單接口, request={}”, data);

                Map response = wxpay.unifiedOrder(data); // 微信sdk集成方法, 統(tǒng)一下單接口unifiedOrder, 此處請求 MD5加密 加密方式

                logger.info(“微信支付下單成功, 返回值 response={}”, response);

                String returnCode = response.get(“return_code”);

                if (!SUCCESS.equals(returnCode)) {

                return null;

                }

                String resultCode = response.get(“result_code”);

                if (!SUCCESS.equals(resultCode)) {

                return null;

                }

                String prepay_id = response.get(“prepay_id”);

                if (prepay_id == null) {

                return null;

                }

                // ******************************************

                //

                // 前端調(diào)起微信支付必要參數(shù)

                //

                // ******************************************

                String packages = “prepay_id=” + prepay_id;

                Map wxPayMap = new HashMap();

                wxPayMap.put(“appId”, iWxPayConfig.getAppID());

                wxPayMap.put(“timeStamp”, String.valueOf(Utility.getCurrentTimeStamp()));

                wxPayMap.put(“nonceStr”, Utility.generateUUID());

                wxPayMap.put(“package”, packages);

                wxPayMap.put(“signType”, “MD5”);

                // 加密串中包括 appId timeStamp nonceStr package signType 5個參數(shù), 通過sdk WXPayUtil類加密, 注意, 此處使用 MD5加密 方式

                String sign = WXPayUtil.generateSignature(wxPayMap, iWxPayConfig.getKey());

                // ******************************************

                //

                // 返回給前端調(diào)起微信支付的必要參數(shù)

                //

                // ******************************************

                result.put(“prepay_id”, prepay_id);

                result.put(“sign”, sign);

                result.putAll(wxPayMap);

                return result;

                } catch (Exception e) {

                }

                回調(diào)結(jié)果處理

                核心是支付訂單回調(diào)時, 需校驗(yàn)加密簽名是否匹配, 防止出現(xiàn)模擬成功通知

                @RequestMapping(value = “/payCallback”, method = RequestMethod.POST)

                public String payCallback(HttpServletRequest request, HttpServletResponse response) {

                logger.info(“進(jìn)入微信支付異步通知”);

                String resXml=””;

                try{

                //

                InputStream is = request.getInputStream();

                //將InputStream轉(zhuǎn)換成String

                BufferedReader reader = new BufferedReader(new InputStreamReader(is));

                StringBuilder sb = new StringBuilder();

                String line = null;

                try {

                while ((line = reader.readLine()) != null) {

                sb.append(line + “”);

                }

                } catch (IOException e) {

                e.printStackTrace();

                } finally {

                try {

                is.close();

                } catch (IOException e) {

                e.printStackTrace();

                }

                }

                resXml=sb.toString();

                logger.info(“微信支付異步通知請求包: {}”, resXml);

                return wxTicketService.payBack(resXml);

                }catch (Exception e){

                logger.error(“微信支付回調(diào)通知失敗”,e);

                String result = “” + “” + “” + ” “;

                return result;

                }

                }

                @Override

                public String payBack(String notifyData) {

                logger.info(“payBack() start, notifyData={}”, notifyData);

                String xmlBack=””;

                Map notifyMap = null;

                try {

                WXPay wxpay = new WXPay(iWxPayConfig);

                notifyMap = WXPayUtil.xmlToMap(notifyData); // 轉(zhuǎn)換成map

                if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {

                // 簽名正確

                // 進(jìn)行處理。

                // 注意特殊情況:訂單已經(jīng)退款,但收到了支付結(jié)果成功的通知,不應(yīng)把商戶側(cè)訂單狀態(tài)從退款改成支付成功

                String return_code = notifyMap.get(“return_code”);//狀態(tài)

                String out_trade_no = notifyMap.get(“out_trade_no”);//訂單號

                if (out_trade_no == null) {

                logger.info(“微信支付回調(diào)失敗訂單號: {}”, notifyMap);

                xmlBack = “” + “” + “” + ” “;

                return xmlBack;

                }

                // 業(yè)務(wù)邏輯處理 ****************************

                logger.info(“微信支付回調(diào)成功訂單號: {}”, notifyMap);

                xmlBack = “” + “” + “” + ” “;

                return xmlBack;

                } else {

                logger.error(“微信支付回調(diào)通知簽名錯誤”);

                xmlBack = “” + “” + “” + ” “;

                return xmlBack;

                }

                } catch (Exception e) {

                logger.error(“微信支付回調(diào)通知失敗”,e);

                xmlBack = “” + “” + “” + ” “;

                }

                return xmlBack;

                }

                統(tǒng)一下單的簽名和后續(xù)前端拉取微信支付的簽名需要統(tǒng)一, 也就是都采用MD5加密, 如果2者不同, 會導(dǎo)致前端拉取微信支付fail, 這是一個巨大的坑, 因?yàn)檫@個原因調(diào)試了好久, 微信在文檔里沒有明確標(biāo)出統(tǒng)一下單的簽名校驗(yàn)方式 需要和前端拉取微信支付的簽名校驗(yàn)保持一致.

                微信sdk里的源碼需要針對這個問題調(diào)整一下, 調(diào)整如下:

                WXPay類需要修改下加密判斷,在WXPay構(gòu)造方法中,調(diào)整如下

                public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception {

                this.config = config;

                this.notifyUrl = notifyUrl;

                this.autoReport = autoReport;

                this.useSandbox = useSandbox;

                if (useSandbox) {

                this.signType = SignType.MD5; // 沙箱環(huán)境

                }

                else {

                this.signType = SignType.MD5; // 將這里的加密方式修改為SignType.MD5, 保持跟前端吊起微信加密方式保持一致

                }

                this.wxPayRequest = new WXPayRequest(config);

                }

                結(jié)束語

                做完以后, 微信支付的后端邏輯還是很清晰的, 但是在開發(fā)過程中很煎熬, 不清楚每個專業(yè)術(shù)語在微信哪里配置, 加密方式亂的很

                鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年7月4日 18:34
                下一篇 2022年7月4日 18:34

                相關(guān)推薦

                • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應(yīng)該怎么發(fā))

                  對于微商朋友來說,朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經(jīng)營一個朋友圈,有的微商看起來逼格滿滿,實(shí)際效果也不錯;而有的卻動都不動就被屏蔽甚至拉黑…

                  2022年11月27日
                • 淘寶工廠店的東西是正品嗎?淘寶工廠店為什么便宜

                  淘工廠直營店其實(shí)就是鏈接淘寶賣家與工廠的平臺,直接對接工廠型的商家,店鋪里的東西大部分價格都會很低。那么,淘工廠直營店靠譜嗎? 淘工廠直營店是靠譜的,但售后問題可能得不到很好的保障…

                  2022年11月27日
                • 存儲過程語法(sql server存儲過程語法)

                  今天小編給各位分享存儲過程語法的知識,其中也會對sql server存儲過程語法進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問題,別忘了關(guān)注本站,現(xiàn)在開始吧! oracle存儲過程基本語法…

                  2022年11月26日
                • 《寶可夢朱紫》夢特性怎么獲得?隱藏特性獲取方法推薦

                  寶可夢朱紫里有很多寶可夢都是擁有夢特性會變強(qiáng)的寶可夢,很多玩家不知道夢特性怎么獲得,下面就給大家?guī)韺毧蓧糁熳想[藏特性獲取方法推薦,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 …

                  2022年11月25日
                • 《寶可夢朱紫》奇魯莉安怎么進(jìn)化?奇魯莉安進(jìn)化方法分享

                  寶可夢朱紫中的奇魯莉安要怎么進(jìn)化呢?很多玩家都不知道,下面就給大家?guī)韺毧蓧糁熳掀骠斃虬策M(jìn)化方法分享,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 奇魯莉安進(jìn)化方法分享 奇魯莉安…

                  2022年11月25日
                • 數(shù)字看亮點(diǎn)!前十月我國造船三大指標(biāo)繼續(xù)全球領(lǐng)先

                  央視網(wǎng)消息:工業(yè)和信息化部最新數(shù)據(jù)顯示,今年1—10月,我國造船三大指標(biāo)繼續(xù)保持全球領(lǐng)先。隨著生產(chǎn)節(jié)奏加快,船企產(chǎn)業(yè)集中度進(jìn)一步提升。 2022年1—10月,全國造船完工量、新接訂…

                  2022年11月25日
                • 前十個月我國造船業(yè)三大指標(biāo)穩(wěn)居世界第一

                  今年1—10月,我國造船業(yè)在國際市場的份額繼續(xù)穩(wěn)居世界第一。一批高技術(shù)高附加值船舶實(shí)現(xiàn)了批量接單、批量生產(chǎn)。 近日,中國船舶上海船舶研究設(shè)計(jì)院又新接了韓國船東三艘汽車運(yùn)輸船的設(shè)計(jì)追…

                  2022年11月25日
                • 規(guī)范透明促PPP高質(zhì)量發(fā)展——16萬億元大市場迎來新規(guī)

                  近日,財政部印發(fā)《關(guān)于進(jìn)一步推動政府和社會資本合作(PPP)規(guī)范發(fā)展、陽光運(yùn)行的通知》,從做好項(xiàng)目前期論證、推動項(xiàng)目規(guī)范運(yùn)作、嚴(yán)防隱性債務(wù)風(fēng)險、保障項(xiàng)目陽光運(yùn)行四個方面進(jìn)一步規(guī)范P…

                  2022年11月25日
                • 客服的崗位職責(zé)怎么寫(客服工作內(nèi)容及職責(zé))

                  各位小伙伴們大家周一好,又到了每周一給大家分享干貨內(nèi)容的時候啦~ 本期來跟大家分享一下客服工作管理流程以及客服崗位里面的每項(xiàng)職能崗位的核心細(xì)則,也是干貨滿滿推薦收藏~ 一.補(bǔ)償流程…

                  2022年11月25日
                • 商家收到貨才會退款嗎(淘寶代付款退款錢到哪里了)

                  在淘寶上有一些人下單購買商品的時候是通過代付的形式來支付的,一般情況下是家長幫助家里的小孩或者長輩進(jìn)行代付,而代付訂單和普通的訂單沒有太大的區(qū)別,不過如果發(fā)生退款的話,錢是退到哪里…

                  2022年11月25日

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時間:周一至周五,10:30-18:30,節(jié)假日休息