微信支付s

微信支付

一、配置文件、配置微信账号

application.yml

#配置微信支付的参数
wxpay:
  appId: wxab8acb865bb1637e
  mchId: 11473623
  key: 2ab9071b06b9f739b950ddb41db2690d
  notifyUrl: http://j19h691179.iok.la/api/wxpay/notify

二、定义配置文件的实体类

WxPayConfig.java

package cn.dm.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "wxpay")
public class WxPayConfig {
    private String appId;
    private String mchId;
    private String notifyUrl;
    private String key;

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public String getMchId() {
        return mchId;
    }

    public void setMchId(String mchId) {
        this.mchId = mchId;
    }

    public String getNotifyUrl() {
        return notifyUrl;
    }

    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

三、编写支付接口

WxPayController.java

package cn.dm.controller;

import cn.dm.common.BaseException;
import cn.dm.common.Constants;
import cn.dm.common.Dto;
import cn.dm.common.DtoUtil;
import cn.dm.config.WxPayConfig;
import cn.dm.exception.ErrorCode;
import cn.dm.exception.PayErrorCode;
import cn.dm.pojo.DmOrder;
import cn.dm.service.DmTradeService;
import cn.dm.util.WXPayConstants;
import cn.dm.util.WXPayRequest;
import cn.dm.util.WXPayUtil;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/api/wxpay")
public class WxPayController {

    @Resource
    private DmTradeService dmTradeService;

    @Resource
    private WxPayConfig wxPayConfig;

    /**
     * 请求统一下单API
     * @param orderNo
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/createqccode/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto createQccode(@PathVariable String orderNo) throws Exception{
        //获取订单信息
        DmOrder dmOrder = dmTradeService.loadDmOrderByOrderNo(orderNo);
        //封装请求下单API所需要的参数
        Map<String, String> data = new HashMap<String, String>();
        data.put("appid", wxPayConfig.getAppId());
        data.put("mch_id", wxPayConfig.getMchId());
        data.put("body", "大觅网抢座下单");
        data.put("out_trade_no", orderNo);
        data.put("total_fee", "1");
        data.put("spbill_create_ip", "192.168.10.107");
        data.put("notify_url", wxPayConfig.getNotifyUrl());
        data.put("trade_type", "NATIVE");
        data.put("nonce_str", WXPayUtil.generateNonceStr());

        //sign签名
        String xml = WXPayUtil.generateSignedXml(data, wxPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
        //带着这些参数去请求统一下单api
        String resultXml = WXPayRequest.requestByXml(xml, "https://api.mch.weixin.qq.com/pay/unifiedorder", wxPayConfig.getMchId());
        //拿到返回结果中的code_url
        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap = WXPayUtil.xmlToMap(resultXml);
        String resultCode = resultMap.get("result_code");
        String codeUrl = "";
        if("SUCCESS".equals(resultCode)){
            codeUrl = resultMap.get("code_url");
            return DtoUtil.returnDataSuccess(codeUrl);
        }else{
            throw new BaseException(PayErrorCode.PAY_ORDER_CODE);
        }
    }


    /**
     * 接收微信官方返回的支付结果通知
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/notify", method = RequestMethod.POST)
    @ResponseBody
    public String paymentCallBack(HttpServletRequest request) throws Exception {
        Map<String, String> result = new HashMap<String, String>();
        //接收微信官方返回的支付结果
        InputStream inputStream = request.getInputStream();
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        String temp;
        StringBuilder stringBuilder =new StringBuilder();
        while ((temp = in.readLine()) != null){
            stringBuilder.append(temp);
        }
        in.close();
        inputStream.close();
        //获取map格式的支付结果
        Map<String, String> resultMap = WXPayUtil.xmlToMap(stringBuilder.toString());
        //签名验证是否正确
        boolean flag = WXPayUtil.isResponseSignatureValid(resultMap, wxPayConfig.getKey());
        if(flag){
            //获取支付结果中的result_code,根据此值判断是否进行自身业务实现
            String resultCode = resultMap.get("result_code");
            if ("SUCCESS".equals(resultCode)){
                //获取微信返回的交易号
                String transactionId = resultMap.get("transaction_id");
                //商户的订单编号
                String orderNo = resultMap.get("out_trade_no");
                if(!dmTradeService.processed(orderNo, Constants.PayMethod.WEIXIN)){
                    //实现自身业务
                    //1.往交易表里面插入记录
                    //2.发消息修改订单的状态
                    System.out.println("实现自身业务");
                }
                result.put("return_code", "SUCCESS");
                result.put("return_msg", "已接收");
            }else{
                result.put("return_code", "FAIL");
                result.put("return_msg", "已接收");
            }
        }else{
            result.put("return_code", "FAIL");
            result.put("return_msg", "已接收");
        }
        //return我们的接收状态
        return WXPayUtil.mapToXml(result);
    }
}
/**
     * 生成带有 sign 的 XML 格式字符串
     *
     * @param data Map类型数据
     * @param key API密钥
     * @param signType 签名类型
     * @return 含有sign字段的XML
     */
   public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception {
        String sign = generateSignature(data, key, signType);
        data.put(WXPayConstants.FIELD_SIGN, sign);
        return mapToXml(data);
    }
/**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key: data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        }
        catch (Exception ex) {
        }
        return output;
    }
/**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

    }
/**
     * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
     *
     * @param reqData 向wxpay post的请求数据
     * @return 签名是否有效
     * @throws Exception
     */
    public static boolean isResponseSignatureValid(Map<String, String> reqData, String key) throws Exception {
        // 返回数据的签名方式和请求中给定的签名方式是一致的
        return WXPayUtil.isSignatureValid(reqData, key, SignType.HMACSHA256);
    }

请求下单的api接口
WXPayRequest.java

package cn.dm.util;

import cn.dm.config.WxPayConfig;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.security.SecureRandom;

public class WXPayRequest {
    public static WxPayConfig config;

    public WXPayRequest(WxPayConfig config) throws Exception {

        this.config = config;
    }

    /**
     * 请求,只请求一次,不做重试
     * @param reqXml
     * @param reqUrl
     * @return
     * @throws Exception
     */
    public static String requestByXml(String reqXml, String reqUrl, String mchId) throws Exception {
        BasicHttpClientConnectionManager connManager;
        connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", SSLConnectionSocketFactory.getSocketFactory())
                        .build(),
                null,
                null,
                null
        );

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost(reqUrl);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(10000).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(reqXml, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", "wxpay sdk java v1.0 "+ mchId);
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");

    }
}

自定义异常

package cn.dm.exception;

import cn.dm.common.IErrorCode;

public enum PayErrorCode implements IErrorCode {
    /**通用异常**/
    COMMON_NO_LOGIN("0001","用户未登录"),
    COMMON_Exception("0002","系统异常"),
    /**节目项目异常**/
    PAY_ORDER_CODE("4001","订单状态异常"),
    PAY_ALIPAY_ERROR_CODE("4002","订单支付异常"),
    PAY_NO_EXISTS("4003","订单不存在"),
    ;
    private String errorCode;
    private String errorMessage;

    private PayErrorCode(String errorCode, String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

}
微信支付是一种移动支付方式,能够让用户在微信平台上完成线上线下的付款。使用微信支付需要调用相应的代码来完成支付流程。下面是一个示例的微信支付代码: 首先,需要获取用户的支付信息,包括商品的价格、订单号等。可以通过前端页面或者后台获取这些信息。 然后,使用微信支付的API来进行支付操作。在C语言中,可以使用HTTP协议发送HTTP请求来调用微信支付API。具体的代码如下: ```c #include <stdio.h> #include <curl/curl.h> int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://api.mch.weixin.qq.com/pay/unifiedorder"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "appid=YOUR_APPID&mch_id=YOUR_MCHID&nonce_str=YOUR_NONCESTR&body=YOUR_BODY&out_trade_no=YOUR_ORDERNO&total_fee=YOUR_AMOUNT&spbill_create_ip=YOUR_IP&notify_url=YOUR_NOTIFYURL&trade_type=APP&sign=YOUR_SIGN"); res = curl_easy_perform(curl); if(res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` 在代码中,需要填入相应的参数,比如YOUR_APPID表示你的应用ID,YOUR_MCHID表示商户号等。其中的sign参数是对请求中的其他参数进行签名得到的,用于校验请求的合法性。 以上是一个简单的微信支付的C代码示例,用于调用微信支付API完成支付操作。当然,具体的代码实现还需要根据实际需求进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值