重慶分公司,新征程啟航
為企業提供網站建設、域名注冊、服務器等服務
為企業提供網站建設、域名注冊、服務器等服務
import com.capinfo.crypt.*;
創新互聯建站-專業網站定制、快速模板網站建設、高性價比永康網站開發、企業建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式永康網站制作公司更省心,省錢,快速模板網站建設找我們,業務覆蓋永康地區。費用合理售后完善,十多年實體公司更值得信賴。
public class RsaTest
{
public RsaTest(){
}
public static void main(String[] args){
//首信公鑰文件
String publicKey = "d:/Public1024.key";
//簽名信息
String SignString = "3e5671bc4f91c3d055b18c1e5e22dd9db157380c7ee8facf0b1117082fbf398d7113c2df7e3219fc28dd88dd26cb096cabe607f3e397dfc2dcdb3349351a5f025ea0761da6e39e2d2fd311294a6076e777fe2ab8911f22113c435b89d63ae4f2aff2f333f7ebd40cc89601d58fb37b16596b5c94eb8b64cd52e12b9679248e6a";
//原信息
String strSource = "abcde12345";
try{
//公鑰驗證
RSA_MD5 rsaMD5 = new RSA_MD5();
int k = rsaMD5.PublicVerifyMD5(publicKey,SignString,strSource);
if(k==0)
System.out.println("驗證成功.");
else
System.out.println("驗證失敗.");
}catch(Exception e){
System.out.println("驗證異常.\n"+e);
}
}
}
1、如果你要做支付功能,技術上很簡單,支付寶有提供接口,改兩個參數就可以用了,非常簡單。2、但是你得網站如果要上線盈利的話,就麻煩了。3、首先你的支付寶收款的賬號要進行商家認證,具體怎么認證我就不知道了,當時是我老板認證的,我就知道這個商家實名認證比個人實名認證麻煩的多。認證之后支付寶會給你兩個參數,一個是合作身份者ID,以2088開頭由16位純數字組成的字符串,一個是商戶的私鑰。你拿到這兩個參數之后去下載支付寶提供的接口程序,把這兩個參數填進去就好了,別的都不用動。當然訂單價格和訂單號的生成規則你可以自己寫。總之支付寶的接口開發的非常完善,而且傻瓜式操作,一看就懂。4、然后你的網站域名要備案,申請ICP證,經營性ICP(為用戶提供有償的信息服務)需要你注冊公司的,而且營業執照很麻煩,我老板現在還在。如果你只是想加個功能,看看接口怎么用,那簡單。但是你要做正規的網站用接口盈利的話,技術上實現很簡單,把程序包下下來,然后改兩個參數,但是合法經營的話需要的手續很多。
JAR(Java ARchive,Java 歸檔)、安裝java軟件就可以了
-------------
JAR(Java ARchive,Java 歸檔)是一種與平臺無關的文件格式,可將多個文件合成一個文件。用戶可將多個 Java applet 及其所需組件(.class 文件、圖像和聲音)綁定到 JAR 文件中,而后作為單個的簡單 HTTP(Hypertext Tranfer Protocal,超文本傳輸協議)事務下載到瀏覽器中,從而大大提高下載速度。JAR 格式也支持壓縮,從而減小了文件的大小,進一步縮短下載時間。另外,applet 編寫者也可在 JAR 文件中用數字簽名的方式簽寫各項以確認其來源。它用 Java 編寫,可與現有的 applet 代碼完全向后兼容且可充分擴展。
本版本的 Java 平臺擴展了 JAR 格式的用途。增強功能包括增加命令行 JAR 工具的功能,可用于創建和更新已簽名的 JAR 文件。同時,它也提供了讀取和寫入 JAR 文件的新的標準 API(Application Programming Interface,應用程序接口)。另外,Java 擴展構架 (Extensions Framework) 也提供了一種機制,用來處理擴展相關性及打包為 JAR 文件的其它第三方庫。
JAR 功能
JAR 指南。
清單和簽名規范
JAR 文件和擴展構架
Java 平臺中的新擴展機制用 JAR 文件格式打包擴展類。為了支持擴展機制和相關功能(如包的密封和版本演變),我們提供了新的清單屬性。有關詳細信息,參見擴展規范。
增強 Jar 工具
Jar 工具提供了新的 -C 和 u 選項,可用于創建和更新 JAR 文件。參見 Jar 工具參考頁:
Jar 工具參考頁 (for Solaris)
Jar 工具參考頁 (for Windows)
讀取和寫入 JAR 文件:API 規范
包 java.util.jar:用來創建和讀取 JAR 文件的類
類 java.net.JarURLConnection:利用 jar 協議實現到 JAR 文件的 URL(Uniform Resource Locators,統一資源定位符)連接的抽象類。
教程
Java Software 站點:
Java 教程中的 Java 歸檔 (JAR) 文件格式。
微信支付系列文章
微信支付-java后端實現
微信支付-vue 前端實現
java demo: 下載地址文章底部
技術棧
Spring boot
java
XML (微信在http協議中數據傳輸方案)
MD5 簽名
微信支付術語
openid (OpenID是公眾號一對一對應用戶身份的標識)
app_id (公眾號id,登錄微信公眾號–開發–基本配置中獲得;)
key (收款商戶后臺進行配置,登錄微信商戶平臺–賬戶中心–API安全-設置秘鑰,設置32位key值;)
mch_id (收款商家商戶號;)
certPath (API證書, 登錄微信商戶平臺–賬戶中心-API安全-下載證書)
后端流程
服務端需要的核心操作, 總共分為以下幾步:
統一下單
前端調起微信支付必要參數 (需加密)
訂單結果主動通知 (回調接口)
查詢訂單結果
結束訂單支付接口(關閉訂單,支付訂單關閉)
代碼
微信總共支持多種語言的sdk, 在官網可以下載例子, java程序也可以引入微信支付的sdk包, 但是github上的sdk已經很久沒有更新了, 最好的選擇, 也是我的選擇, 在官網上下載sdk項目, 將其中所有java類copy到自己的項目中.
官網sdk下載目錄
鏈接: 商戶平臺首頁
#### 根據微信sdk生成配置類 WXPayConfig
創建IWxPayConfig.class, 繼承sdk WXPayConfig.class, 實現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 實現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 { // 構造方法讀取證書, 通過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() { // 這個方法需要這樣實現, 否則無法正常初始化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;
}
}
發起統一下單 AND 前端調起微信支付必要參數
// 發起微信支付
WXPay wxpay = null;
Map result = new HashMap();
try {
// ******************************************
//
// 統一下單
//
// ******************************************
wxpay = new WXPay(iWxPayConfig); // *** 注入自己實現的微信配置類, 創建WXPay核心類, WXPay 包括統一下單接口
Map data = new HashMap ();
data.put("body", "訂單詳情");
data.put("out_trade_no", transOrder.getGlobalOrderId()); // 訂單唯一編號, 不允許重復
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); // 微信公眾號統一標示openid
data.put("notify_url", ""); // 訂單結果通知, 微信主動回調此接口
data.put("trade_type", "JSAPI"); // 固定填寫
logger.info("發起微信支付下單接口, request={}", data);
Map response = wxpay.unifiedOrder(data); // 微信sdk集成方法, 統一下單接口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;
}
// ******************************************
//
// 前端調起微信支付必要參數
//
// ******************************************
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個參數, 通過sdk WXPayUtil類加密, 注意, 此處使用 MD5加密 方式
String sign = WXPayUtil.generateSignature(wxPayMap, iWxPayConfig.getKey());
// ******************************************
//
// 返回給前端調起微信支付的必要參數
//
// ******************************************
result.put("prepay_id", prepay_id);
result.put("sign", sign);
result.putAll(wxPayMap);
return result;
} catch (Exception e) {
}
回調結果處理
核心是支付訂單回調時, 需校驗加密簽名是否匹配, 防止出現模擬成功通知
@RequestMapping(value = "/payCallback", method = RequestMethod.POST)
public String payCallback(HttpServletRequest request, HttpServletResponse response) {
logger.info("進入微信支付異步通知");
String resXml="";
try{
//
InputStream is = request.getInputStream();
//將InputStream轉換成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("微信支付回調通知失敗",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); // 轉換成map
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
// 簽名正確
// 進行處理。
// 注意特殊情況:訂單已經退款,但收到了支付結果成功的通知,不應把商戶側訂單狀態從退款改成支付成功
String return_code = notifyMap.get("return_code");//狀態
String out_trade_no = notifyMap.get("out_trade_no");//訂單號
if (out_trade_no == null) {
logger.info("微信支付回調失敗訂單號: {}", notifyMap);
xmlBack = " ";
return xmlBack;
}
// 業務邏輯處理 ****************************
logger.info("微信支付回調成功訂單號: {}", notifyMap);
xmlBack = " ";
return xmlBack;
} else {
logger.error("微信支付回調通知簽名錯誤");
xmlBack = " ";
return xmlBack;
}
} catch (Exception e) {
logger.error("微信支付回調通知失敗",e);
xmlBack = " ";
}
return xmlBack;
}
統一下單的簽名和后續前端拉取微信支付的簽名需要統一, 也就是都采用MD5加密, 如果2者不同, 會導致前端拉取微信支付fail, 這是一個巨大的坑, 因為這個原因調試了好久, 微信在文檔里沒有明確標出統一下單的簽名校驗方式 需要和前端拉取微信支付的簽名校驗保持一致.
微信sdk里的源碼需要針對這個問題調整一下, 調整如下:
WXPay類需要修改下加密判斷,在WXPay構造方法中,調整如下
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; // 沙箱環境
}
else {
this.signType = SignType.MD5; // 將這里的加密方式修改為SignType.MD5, 保持跟前端吊起微信加密方式保持一致
}
this.wxPayRequest = new WXPayRequest(config);
}
結束語
做完以后, 微信支付的后端邏輯還是很清晰的, 但是在開發過程中很煎熬, 不清楚每個專業術語在微信哪里配置, 加密方式亂的很
支付平臺程序??+[Q]845567777
【程序】?API支付平臺程序?(適用?第三方?第四方?支付平臺搭建?等)
【語言】Java
【數據庫】mysql
【程序優點】
JAVA語言編寫,安全、高效、快捷,通過本API系統程序可快速搭建自己的支付平臺,有支付接口即可發展商戶。
國內支付平臺程序首批Java程序國內外大型企業、銀行、第三方企業級的站?等都用JAVA開發
JAVA安全性?穩定性?極高,跨平臺等優點
其他語言asp?php?net等和JAVA比不是一個檔次
【更多功能】
★本平臺程序?接口?兼容?易寶支付接口。只要客戶網站有易寶接口,直接換掉?提交地址?和?ID密鑰?即可使用
★兼容點卡和網銀、支持直連接入、非直連接入、在線充值。直接接入就是在自己的網站上寫入銀行編碼、請求的時候直接到銀行非直連的意思就是不需要在自己的網站寫網銀編碼、在系統上提交到銀行
★特有功能:扣單、恢復訂單、銀行拆分、獨立支付寶、獨立網銀?等后臺訂單明細特別清晰?后臺明細多種方式??并非那些小平臺可比