java實現掃碼槍-微信支付
2024-08-1367釋出于山東
版權
簡介: java實現掃碼槍-微信支付
實現 Java 掃碼槍支付的微信支付功能涉及幾個步驟,包括獲取微信支付 API 憑證、生成支付二維碼、掃描二維碼並獲取支付結果。以下是一個完整的實現示例,包括詳細的註釋。
步驟 1:準備工作
確保你已經註冊了微信支付賬號,並獲得了以下資訊:
- 商戶號(mch_id)
- 應用ID(app_id)
- API 金鑰(api_key)
步驟 2:新增依賴
在你的專案中新增必要的依賴。例如,如果你使用的是 Maven
專案,可以在 pom.xml
檔案中新增以下依賴:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.3</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.15</version> </dependency>
步驟 3:生成微信支付二維碼
以下程式碼示例演示如何生成微信支付二維碼:
import java.util.HashMap; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import com.fasterxml.jackson.databind.ObjectMapper; public class WeChatPayQRCode { private static final String WECHAT_PAY_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; private static final String APP_ID = "your_app_id"; private static final String MCH_ID = "your_mch_id"; private static final String API_KEY = "your_api_key"; private static final String NOTIFY_URL = "http://your_notify_url"; private static final String TRADE_TYPE = "NATIVE"; public static void main(String[] args) throws Exception { String productId = UUID.randomUUID().toString().replaceAll("-", ""); String qrCodeUrl = generateWeChatQRCode("Test Product", productId, 1); System.out.println("QR Code URL: " + qrCodeUrl); } public static String generateWeChatQRCode(String productDescription, String productId, int totalFee) throws Exception { SortedMap<String, String> params = new TreeMap<>(); params.put("appid", APP_ID); params.put("mch_id", MCH_ID); params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", "")); params.put("body", productDescription); params.put("out_trade_no", productId); params.put("total_fee", String.valueOf(totalFee)); params.put("spbill_create_ip", "127.0.0.1"); params.put("notify_url", NOTIFY_URL); params.put("trade_type", TRADE_TYPE); String sign = generateSignature(params, API_KEY); params.put("sign", sign); String xmlRequest = mapToXml(params); String responseXml = sendPost(WECHAT_PAY_URL, xmlRequest); Map<String, String> responseMap = xmlToMap(responseXml); if ("SUCCESS".equals(responseMap.get("return_code")) && "SUCCESS".equals(responseMap.get("result_code"))) { return responseMap.get("code_url"); } else { throw new RuntimeException("Failed to generate WeChat QR Code: " + responseMap.get("return_msg")); } } private static String generateSignature(SortedMap<String, String> params, String apiKey) throws Exception { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (entry.getValue() != null && !"".equals(entry.getValue()) && !"sign".equals(entry.getKey())) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } } sb.append("key=").append(apiKey); return org.apache.commons.codec.digest.DigestUtils.md5Hex(sb.toString()).toUpperCase(); } private static String mapToXml(SortedMap<String, String> params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append("<").append(entry.getKey()).append(">").append(entry.getValue()).append("</").append(entry.getKey()).append(">"); } sb.append("</xml>"); return sb.toString(); } private static String sendPost(String url, String xml) throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(xml, "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPost); try { return EntityUtils.toString(response.getEntity(), "UTF-8"); } finally { response.close(); httpClient.close(); } } private static Map<String, String> xmlToMap(String xml) throws Exception { ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(xml, HashMap.class); } }
步驟 4:處理掃碼槍輸入
掃碼槍通常作為鍵盤輸入裝置工作,因此可以直接讀取輸入內容。
import java.util.Scanner; public class ScannerInput { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("請掃描二維碼:"); while (scanner.hasNextLine()) { String input = scanner.nextLine(); System.out.println("掃碼內容: " + input); // 在這裡呼叫支付查詢介面,檢查支付狀態 // checkPaymentStatus(input); } } }
步驟 5:查詢支付狀態
import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import com.fasterxml.jackson.databind.ObjectMapper; public class WeChatPayQuery { private static final String WECHAT_PAY_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery"; private static final String APP_ID = "your_app_id"; private static final String MCH_ID = "your_mch_id"; private static final String API_KEY = "your_api_key"; public static void main(String[] args) throws Exception { String orderId = "your_order_id"; String result = checkPaymentStatus(orderId); System.out.println("支付結果: " + result); } public static String checkPaymentStatus(String orderId) throws Exception { SortedMap<String, String> params = new TreeMap<>(); params.put("appid", APP_ID); params.put("mch_id", MCH_ID); params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", "")); params.put("out_trade_no", orderId); String sign = generateSignature(params, API_KEY); params.put("sign", sign); String xmlRequest = mapToXml(params); String responseXml = sendPost(WECHAT_PAY_QUERY_URL, xmlRequest); Map<String, String> responseMap = xmlToMap(responseXml); if ("SUCCESS".equals(responseMap.get("return_code")) && "SUCCESS".equals(responseMap.get("result_code"))) { return responseMap.get("trade_state"); } else { throw new RuntimeException("Failed to query WeChat payment status: " + responseMap.get("return_msg")); } } private static String generateSignature(SortedMap<String, String> params, String apiKey) throws Exception { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (entry.getValue() != null && !"".equals(entry.getValue()) && !"sign".equals(entry.getKey())) { sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } } sb.append("key=").append(apiKey); return org.apache.commons.codec.digest.DigestUtils.md5Hex(sb.toString()).toUpperCase(); } private static String mapToXml(SortedMap<String, String> params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, String> entry : params.entrySet()) { sb.append("<").append(entry.getKey()).append(">").append(entry.getValue()).append("</").append(entry.getKey()).append(">"); } sb.append("</xml>"); return sb.toString(); } private static String sendPost(String url, String xml) throws Exception { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(xml, "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPost); try { return EntityUtils.toString(response.getEntity(), "UTF-8");