These docs are for v3.2.6. Click to read the latest docs for v4.3.0.

Wechat Miniprogram

Payment Flow


  1. Merchant retrieve OpenID using “wx.login’s code” and “code2session api”
  2. Merchant make API call to 2C2P to get the wx.requestPayment (prepay_id)
  3. Merchant Invoke wx.requestPayment in MiniProgram
  4. WeChat shall prompt customer to confirm payment
  5. Wechat shall display payment result to customer
  6. WeChat shall notify a notification from 2C2P regarding payment result
  7. 2C2P shall notify payment result to Merchant

 

Getting OpenID


  1. Merchant shall invoke “wx.login” in miniprogram to get “code”
    Document: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html
  2. Merchant shall submit “code” to merchant’s backend to retrieve openID
    Document: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

 

Integration Guide


  1. Make SecurePay Payment
    1.1) Information to make Wechat MiniProgram
  • paymentChannel is WCMINI
  • miniProgramData show following. Required appID & openID
<miniProgramData>
    <wechat>
      <appID>{appid}</appID>
      <openID>{openid}</openID>
    </wechat>
</miniProgramData>
  1. You will receive the response back from 2C2P with response code “32”
  2. You will read the “miniProgramData/wechat” xml tag to receive the wx.requestPayment payload

📘

Refer Wechat Request Payment Parameter

<miniProgramData>
    <wechat>
      {"timeStamp":"","package":"","nonceStr":"","signType":"","paySign":""}
    </wechat>
</miniProgramData>

 
Sample code show following

🚧

Environment

Please refer Demo & Live Endpoint.

📘

Secure Pay API

Refer Payload Refer Payload Parameter Specification & API Parameter Specification

#region ALL Fields

string cardholderEmail = "", payCategoryID = "", userDefined1 = "", userDefined2 = "", userDefined3 = "", userDefined4 = "", userDefined5 = "", storeCard = "",
    ippTransaction = "", installmentPeriod = "", interestType = "", recurring = "", invoicePrefix = "", recurringAmount = "", allowAccumulate = "", maxAccumulateAmt = "",
    recurringInterval = "", recurringCount = "", chargeNextDate = "", promotion = "", request3DS = "", statementDescriptor = "", agentCode = "", channelCode = "", paymentExpiry = "", mobileNo = "", tokenizeWithoutAuthorization = "",
    paymentChannel = "", storeCardUniqueID = "", panBank = "", userId = "", storeId = "", storeName = "", storeTerminalId = "", wxAppId = "", wxOpenId = "";

#endregion

// RETRIEVE merchantId, merchantSecretKey from your database
//Merchant Account Information
string merchantID = "JT01"; //Get MerchantID from 2c2p PGW Dashboard
string secretKey = "7jYcp4FxFdf0"; //Get SecretKey from 2c2p PGW Dashboard

//Product Information
string uniqueTransactionCode = "Invoice" + DateTime.Now.ToString ("yyMMddHHmmss");
string desc = "item 1";
string amt = "000000000001"; //12 digit format
string currencyCode = "702"; //Ref: http://en.wikipedia.org/wiki/ISO_4217

//Customer Information
string cardholderName = "John Doe";
string country = "SG";

//Payment Channel
paymentChannel = "WCMINI"; // Wechat App 

string miniprogramData = "";
wxAppId = "wx0ecdd8f41c8ac9ab"; // app id
wxOpenId = paymentData.openId; // openid
miniprogramData = "<wechat>" +
  "<appID>" + wxAppId + "</appID>" +
  "<openID>" + wxOpenId + "</openID>" +
  "</wechat>";

//Request Information
string timeStamp = DateTime.Now.ToString ("ddMMyyHHmmss");
string apiVersion = "9.9";

//Construct payment request message
string payloadXml = "<PaymentRequest>" +
    "<timeStamp>" + timeStamp + "</timeStamp>" +
    "<merchantID>" + merchantID + "</merchantID>" +
    "<uniqueTransactionCode>" + uniqueTransactionCode + "</uniqueTransactionCode>" +
    "<desc>" + HttpUtility.HtmlEncode (desc) + "</desc>" +
    "<amt>" + amt + "</amt>" +
    "<currencyCode>" + currencyCode + "</currencyCode>" +
    "<panCountry>" + country + "</panCountry>" +
    "<cardholderName>" + cardholderName + "</cardholderName>" +
    "<paymentChannel>" + paymentChannel + "</paymentChannel>" +
    "<miniProgramData>" +
    miniprogramData +
    "</miniProgramData>" +
    "</PaymentRequest>";

string payload = Utility.Base64Encode (payloadXml); //Convert payload to base64  
string hash = Utility.GetHMAC2 (payload, secretKey); //Calculate Hash Value

string xml = "<PaymentRequest>" +
    "<version>" + apiVersion + "</version>" + //request version number (9.9)
    "<payload>" + payload + "</payload>" + //request payload
    "<signature>" + hash + "</signature>" + //signature
    "</PaymentRequest>";

string data = Utility.Base64Encode (xml); //Convert payload to base64          
data = "paymentRequest=" + HttpUtility.UrlEncode (data); //urlEncode data

string url = "https://demo2.2c2p.com/2C2PFrontEnd/SecurePayment/Payment.aspx";

var paymentResponse = Utility.PostRequest (url, data, Utility.PostContentType.FORM);
if (paymentResponse.Result) {
    if (!string.IsNullOrEmpty (paymentResponse.ResultOutput)) {
        string clearResult = Utility.Base64Decode (paymentResponse.ResultOutput);
        XmlDocument xDoc = new XmlDocument ();
        xDoc.LoadXml (clearResult);
        string respPayload = (xDoc.SelectNodes ("//payload").Count > 0 ? xDoc.SelectSingleNode ("//payload").InnerText : "");
        string respSign = (xDoc.SelectNodes ("//signature").Count > 0 ? xDoc.SelectSingleNode ("//signature").InnerText : "");

        string respHash = Utility.GetHMAC2 (respPayload, secretKey); //Calculate Hash Value

        respPayload = Utility.Base64Decode (respPayload);
        if (respHash.Equals (respSign, StringComparison.OrdinalIgnoreCase)) {
            XmlDocument xDocResponse = new XmlDocument ();
            xDocResponse.LoadXml (respPayload);
            string respCode = (xDocResponse.SelectNodes ("//respCode").Count > 0 ? xDocResponse.SelectSingleNode ("//respCode").InnerText : "");
            if (respCode == "32") {
               string wechatData = (xDocResponse.SelectNodes ("//miniProgramData//wechat").Count > 0 ? xDocResponse.SelectSingleNode ("//miniProgramData//wechat").InnerText : "");
               return Json (wechatData); 
            } else {
                return BadRequest ("Failed to get requestPayment");
            }

        } else {
            return BadRequest ();
        }
    } else {
        return BadRequest ("Empty response");
    }
} else {
    return BadRequest (paymentResponse.ErrorDetails);
}