UnionPay payment to realize code docking

The payment effect can be seen at the end of the article.

Students who have paid for it know that Alipay and WeChat payments are only suitable for small payments. If they encounter large business scenarios, they still have to pay for them.

Like other payment platforms, UnionPay also provides corresponding payment channels according to different mobile terminals, such as online gateway payment, cloud flash payment APP payment (original mobile payment control), enterprise online banking payment (merchant version), mobile web page payment (WAP payment), QR code payment, etc.

The first step to connect to the platform interface is naturally to have an account. I won't say much about the process of registering an account. Put it on the official website and register yourself.
(https://open.unionpay.com/)

Select the products to be connected, fill in the information and submit the network access application, and there will be business connection.

It is very friendly that the platform will provide test parameters for debugging the interface. In the personal Center - merchant network access test center - test parameters, including test merchant number, test certificate and test address.

With these things, you can start writing code and debugging interfaces. Of course, the most comforting thing is that the platform also provides SDK for your reference. After measurement, it is really only for reference, because you can't run, ha ha 😀.
Although the code is very simple, it still takes effort to integrate successfully.

acp_ The sdk.properties configuration file mainly places some certificate files, which are downloaded from the merchant network access test center.

########################## Transaction sending address of network access test environment #############################
# Message version number, fixed 5.1.0
acpsdk.version=5.1.0

# Signature method, certificate method fixed 01
acpsdk.signMethod=01

##Test transaction request address
acpsdk.frontTransUrl=https://gateway.test.95516.com/gateway/api/frontTransReq.do
acpsdk.backTransUrl=https://gateway.test.95516.com/gateway/api/backTransReq.do
acpsdk.singleQueryUrl=https://gateway.test.95516.com/gateway/api/queryTrans.do

# Whether to verify the CN of the signing certificate, set false for the test environment and true for the production environment.
acpsdk.ifValidateCNName=false

# Whether to verify the https certificate, set false for the test environment and true for the production environment.
acpsdk.ifValidateRemoteCert=false

######################### Network access test environment signature certificate configuration ################################
# Signature certificate path
acpsdk.signCert.path=/data/acp_test_sign.pfx

# Signature certificate password, test environment fixed 000000
acpsdk.signCert.pwd=000000
# The signature certificate type is fixed and does not need to be modified
acpsdk.signCert.type=PKCS12

########################## Encryption certificate configuration ################################
# Sensitive information encryption certificate path
acpsdk.encryptCert.path=/data/acp_test_enc.cer

########################## Signature verification certificate configuration ################################
# Intermediate certificate verification path
acpsdk.middleCert.path=/data/acp_test_middle.cer
# Verify root certificate path
acpsdk.rootCert.path=/data/acp_test_root.cer

ACP_ Put the sdk.properties configuration file in the root directory

Write another configuration class, UnionPayConfig, and load the certificate content when starting

@Component
@Configuration
@EnableConfigurationProperties({UnionProperties.class})
public class UnionPayConfig {
    private UnionProperties union;
    public UnionPayConfig(UnionProperties union) {
        this.union = union;
        SDKConfig.getConfig().loadPropertiesFromSrc();
    }
}

The PC side calls up the payment page. Pay attention to the transaction amount. The unit is minute, and there can be no decimal point. The result is to open the payment page in the form of form.

@GetMapping(value="webPay")
    public void  webPay(HttpServletResponse resp) throws IOException {
        logger.info("UnionPay computer payment");
        UnionPayParam param = new UnionPayParam();
        param.setOrderId(UnionConfig.getCurrentTime())
                .setTxnTime(UnionConfig.getCurrentTime())
                .setTxnAmt("330000")
                .setReqReserved(param.getOrderId());
        unionPayService.webPay000202(param, resp);
        Map<String, String> data = new HashMap<>(29);
        // Version number, Omni channel default
        data.put("version", UnionConfig.version);
        // For character set encoding, UTF-8 and GBK can be used
        data.put("encoding", UnionConfig.encoding_UTF8);
        // Signature method
        data.put("signMethod", SDKConfig.getConfig().getSignMethod());
        // Transaction type, 01: consumption
        data.put("txnType", "01");
        // Transaction subtype, 01: self service consumption
        data.put("txnSubType", "01");
        // Business type 000202: B2B
        data.put("bizType", "000202");
        // Channel type fixed 07
        data.put("channelType", "07");
        // Merchant number
        data.put("merId", unionProperties.getMerId());
        // Access type, 0: direct merchant
        data.put("accessType", "0");
        // Merchant order number, 8-40 digits, alphanumeric, can not contain "-" or "", and can customize the rules
        data.put("orderId", param.getOrderId());
        // The order sending time takes the system time in the format of YYYYMMDDhhmmss. The current time must be taken, otherwise txnTime will be reported as invalid
        data.put("txnTime", param.getTxnTime());
        // Transaction currency (generally 156 yuan for domestic merchants)
        data.put("currencyCode", "156");
        // Transaction amount, unit: Fen, without decimal point
        data.put("txnAmt", CommonUtils.subZeroAndDot(param.getTxnAmt()));
        // For business scenarios, refer to the interface specification for values
        data.put("bizScene", "110001");
        // Payee account name
        data.put("payeeAcctNm", URLEncoder.encode(unionProperties.getPayeeAcctNm(),UnionConfig.encoding_UTF8));
        // Payee account number
        data.put("payeeAcctNo", unionProperties.getPayeeAcctNo());
        // Name of receiving bank
        data.put("payeeBankName", URLEncoder.encode(unionProperties.getPayeeBankName(),UnionConfig.encoding_UTF8));
        // Front desk notification address
        data.put("frontUrl", unionProperties.getFrontUrl());
        // Background notification address
        data.put("backUrl", unionProperties.getBackUrl());
        // Order timeout
        data.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(System.currentTimeMillis() + 15 * 60 * 1000));
        // When the requestor reserves the field and the content will not appear "& = {} []", you can fill in the data directly
        data.put("reqReserved", Base64.encodeBase64String(param.getReqReserved().getBytes(UnionConfig.encoding_UTF8)));
        Map<String, String> reqData = AcpUtils.sign(data,UnionConfig.encoding_UTF8);
        String requestFrontUrl = SDKConfig.getConfig().getFrontRequestUrl();
        String html = AcpUtils.createAutoFormHtml(requestFrontUrl,reqData,UnionConfig.encoding_UTF8);
        logger.info("Print request HTML,This is a request message:{}", html);
        resp.getWriter().write(html);

Like other payment methods, the payment result is notified to the developer by asynchronous notification, where the business logic is processed, such as changing the order status to paid.

@PostMapping(value="unionPayNotify")
    public void unionPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("Start of UnionPay receiving background notification");
        String encoding = request.getParameter(SDKConstants.param_encoding);
        // Get the background notification parameters sent by UnionPay notification server
        Map<String, String> reqParam = AcpUtils.getAllRequestParam(request);
        Map<String, String> valideData = new HashMap<>();
        if (!reqParam.isEmpty()) {
            Iterator<Map.Entry<String, String>> it = reqParam.entrySet().iterator();
            valideData = new HashMap<>(reqParam.size());
            while (it.hasNext()) {
                Map.Entry<String, String> e = it.next();
                String key = e.getKey();
                String value = e.getValue();
                value = new String(value.getBytes(encoding), encoding);
                valideData.put(key, value);
            }
        }
        if (!AcpUtils.validate(valideData, encoding)) {
            logger.info("UnionPay verification signature result[fail].");
        } else {
            logger.info("UnionPay callback result parameters=====: {}", JSON.toJSONString(valideData));
            logger.info("UnionPay verification signature result[success].");
            AsyncNotifyResult result = JSON.parseObject(JSON.toJSONString(valideData), AsyncNotifyResult.class);
            // Response code
            String respCode = result.getRespCode();
            // Response information
            String respMsg = result.getRespMsg();
            if (StringUtils.equals("00", respCode) && StringUtils.equals("success[0000000]", respMsg)) {
                // Merchant order number
                String orderId = result.getOrderId();
                // UnionPay inquiry serial number
                String queryId = result.getQueryId();
                // UnionPay order sending time
                String txnTime = result.getTxnTime();

                String txnAmt = result.getTxnAmt();
                // Auxiliary information
                String reqReserved = result.getReqReserved();
                logger.info("reqReserved=====: {}", new String(Base64.decodeBase64(reqReserved), UnionConfig.encoding_UTF8));
                // TODO
                // UnionPay does not return the payment time, which is generated by the system itself
                logger.info("Process business logic, orderId: {},to update queryId: {},txnTime: {}=====", orderId, queryId, txnTime);

            }
            response.getWriter().print("ok");
        }
    }

Look at the effect

This is the test environment. Select the card number, enter the verification code, and click Submit

If code is required

UnionPay payment to realize code docking

The scenery meets, the future can be expected, thank you for reading, we'll see you again

The golden cudgel in my hand can reach the sky and explore the sea

Previous: Alipay small program template development, a complete set of processes

Keywords: Java

Added by jola on Sun, 05 Dec 2021 18:14:47 +0200